参数传递分为单个参数、多个参数。
Student findStudent(int id);
<select id="findStudent" parameterType="int" resultType="com.ffyc.mybatis.modle.Student">
select name,gender from student where id = #{id}
select>
注意:select中的id应当与代理接口中的方法名相同,parameterType表示传过来的参数的类型,resultType表示返回值的类型。
public void test(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = studentDao.findStudent(1);
System.out.println(student);
sqlSession.close();
}
传递多个参数时需要在代理接口中使用@Param(“id”)绑定,其他步骤不变。
如:
Student selectStudent(@Param("name") String name , @Param("id") int id);
如果参数过多,并且具有一定的规范,可以传递一个对象,此时就需要使用parameterType参数进行定义类型,如:
//代理接口中
void insert(Student student);
<insert id="insert" parameterType="Student">
insert into student (name,gender) values (#{name},#{gender})
insert>
注意:parameterType属性可以直接写Student是因为在mybatisConfig.xml中使用了别名配置:
<typeAliases>
<package name="com.ffyc.mybatis.modle"/>
typeAliases>
在上面的案例中已经有新增的例子了
新增时如果只将代理对象中的方法声明为int类型的返回值时返回的是执行此操作改变的行数。
//代理接口中
int insert(Student student);
在测试中执行完测试方法后数据库表的数据并没有变化,是因为我们使用的是JDBC的事物管理,在所打印的日志“Setting autocommit to false on JDBC Connection”可以看出,Mybatis中的JDBC自动提交管理是false关闭的 ,需要我们手动提交。
public void test(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = new Student();
student.setGender("男");
student.setName("大黑");
studentDao.insert(student);
sqlSession.commit();//提交数据库事务管理,告诉mysql所有的逻辑已经执行完了,你可以将所有sql语句执行了
sqlSession.close();
}
注意:只有在增删改查中需要手动提交事务管理。
当有需求是:须知道插入数据的id时(id为自增的)只需要在Mapper.xml文件的对应添加标签中声明几个属性就好
<insert id="insert" parameterType="Student" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
insert into student (name,gender) values (#{name},#{gender})
insert>
是经过预编译的编译好的SQL语句在取值,底层使用的是PreparedStatement对象,是安全的数据库访问#{}的方式可以有效地防止SQL注入。一般传值时使用。
会传入参数字符串,取值后再去编译SQL语句,${}的方式无法防止SQL注入。一般用来动态传递列名。
Mybatis排序时使用order by 动态传参时用的是$ 而不是 #。
int upDate(Student student);
<update id="upDate" parameterType="Student">
update student set name=#{name},gender=#{gender} where id = #{id}
update>
@Test
public void test2(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = new Student(5,"leukemia","女");
studentDao.upDate(student);
sqlSession.commit();
sqlSession.close();
}
与之前一样
int Delete(int id);
<delete id="Delete" parameterType="int">
delete from student where id = #{id}
delete>
@Test
public void test3(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
studentDao.Delete(5);
sqlSession.commit();
sqlSession.close();
}
我们当时在jdbc中查询到结果时需要循环,一个个手动的封装到对应属性当中
如:
while (resultSet.next()) {
Students student = new Students();
student.setId(resultSet.getInt("id"));
student.setNum(resultSet.getString("num"));
student.setName(resultSet.getString("name"));
student.setGender(resultSet.getString("gender"));
student.setPhone(resultSet.getString("phone"));
student.setGradeName(resultSet.getString("grade"));
student.setAdminName(resultSet.getString("account"));
student.setOpertime(resultSet.getTimestamp("oper_time"));
list.add(student);
}
使用Mybatis时就不需要在手动封装。
查询结果为一条数据时,可以实现将记录自动封装到对象中,实现方法有:
当数据库表中列名含有下划线时,如:
student_phone CHAR(11)
可以在对应的实体类将属性严格按照驼峰命名
private String studentPhone;
并且在mybatisConfig.xml配置文件中进行一个setting全局配置
<setting name="mapUnderscoreToCamelCase" value="true"/>
select name,gender six,student_phone from student where id = #{id}
<resultMap id="findStudentMap" type="Student">
<result column="gender" property="six">result>
resultMap>
<select id="findStudentById" resultMap="findStudentMap">
select name,gender,student_phone from student where id = #{id}
select>
查询结果为多条结果时
查询结果为多条数据时,非常简单,只需要将代理接口中的方法的返回值类型改为list集合就行
List<Student> findStudent();
之前在jdbc中我们使用的是直接列所表示的意思当做一个私有属性,如:
在创建学生对象时,学生表中会有年级id,对应到具体的某一个年级,在jdbc中是创建私有属性
private String gradeName;
private int gradeid;
在Mybatis中只需要创建一个年级的私有属性就好
private Grade grade;
在对应的Mapper.xml文件中的写法如下:
<resultMap id="findStudentMap" type="student">
<id column="id" property="id">id>
<result column="gender" property="gender">result>
<result column="name" property="name">result>
<result column="student_phone" property="studentPhone">result>
<association property="grade" javaType="Grade">
<result column="gname" property="name">result>
association>
resultMap>
<select id="findStudentById" resultMap="findStudentMap">
SELECT
s.id,
s.name,
s.gender,
s.student_phone,
g.name gname
FROM
student s
LEFT JOIN grade g
ON s.gradeid = g.id
WHERE s.id = #{id}
select>
需要注意的是:
<result column="id" property="id">result>
<result column="gender" property="gender">result>
<result column="name" property="name">result>
<result column="student_phone" property="studentPhone">result>
按照之前所学习的内容,这些属性名与列名相匹配,可以不写,但是当有嵌套结果映射时,自动映射就停止了。
也是可以修改的。在配置文件中myBatisConfig.xml中
<setting name="autoMappingBehavior" value="FULL"/>
FULL:开启时,就会完全自动映射。当然也会存在问题,只要名字相同就会映射,如:在没有起别名的情况下,没有查询年级的id,但是Mybatis会自动将学生的id封装进年级的id中。
NONE:不自动映射;PARTIAL:(默认的)单张表自动映射,有嵌套关联时关闭自动映射;FULL:一直开启自动映射。
如果想查询学生集合时:
List<Student> findStudentList();
<select id="findStudentList" resultMap="findStudentMap">
SELECT
s.id,
s.name,
s.gender,
s.student_phone,
g.name gname
FROM
student s
LEFT JOIN grade g
ON s.gradeid = g.id
select>
由以上代码知,在查询集合和查询单条数据都可以用同一条resultMap。
查询集合和查询单条数据的SQL语句大体相同,可以将SQL抽取出来:
<select id="findStudentList" resultMap="findStudentMap">
<include refid="selectStudent">include>
select>
<sql id="selectStudent">
SELECT
s.id,
s.name,
s.gender,
s.student_phone,
g.name gname
FROM
student s
LEFT JOIN grade g
ON s.gradeid = g.id
sql>
例如:一个年级有很多学生,现在需要查询出某个年级的所有学生。
//年级实现类
public class Grade {
private Integer id;
private String name;
private Set<Student> students = new HashSet<>();
}
对应Mapper.xml文件中:
<resultMap id="findGradeStudentMap" type="Grade">
<id column="gid" property="id"/>
<result column="gname" property="name"/>
<collection property="students" javaType="java.util.HashSet" ofType="Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="gender" property="gender"/>
collection>
resultMap>
<select id="findGradeStudent" resultMap="findGradeStudentMap">
SELECT
s.id,
s.name,
s.gender,
g.id gid,
g.name gname
FROM
grade g
LEFT JOIN student s
ON s.gradeid = g.id
select>
将一个多表关联查询拆分为多次查询,先查询主表数据,然后查询关联表数据。
先查出年级,通过年级在查学生。
<resultMap id="findGradeStudentMap2" type="Grade">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="students" javaType="list" ofType="Student" select="findStudent" column="id">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="gender" property="gender"/>
collection>
resultMap>
<select id="findStudent" resultType="Student">
select id,name,gender from student where gradeid=#{id}
select>
<select id="findGradeStudent2" resultMap="findGradeStudentMap2">
SELECT
g.id ,
g.name
FROM
grade g
select>
(1). select:指定关联查询对象的 Mapper Statement ID 为 findStudent
(2). column=“id”:关联查询时将 id列的值传入 findStudent,并将 findStudent查询的结果映射到 Grade的 students属性中
(3).collection 和 association 都需要配置 select 和 column 属性,两者配置方法相同
@Insert : 插入 sql , 和 xml insert sql 语法完全一样
如:
@Insert("insert into grade (name) value (#{name})")
void insert(String name);
@Select : 查询 sql, 和 xml select sql 语法完全一样
@Update : 更新 sql, 和 xml update sql 语法完全一样
@Delete : 删除 sql, 和 xml delete sql 语法完全一样
@Param : 入参
@Results : 设置结果集合
@Result : 结果