MyBatis注解开发

1.使用注解配置SQL映射器

上一章中,我们看到了映射器Mapper XML的使用。其实MyBatis也支持使用注解的方式来进行SQL的映射,只不过这中方式使用更少一些。本章将涵盖以下的话题:

  • 在映射器Mapper接口上使用注解
  • 映射语句
    @Insert、@Update、@Delete、@SelectStatements
  • 结果映射
    一对一映射、一对多映射
  • 动态SQL
    SelectProvider
    InsertProvider
    UpdateProvider
    DeleteProvider

2.在映射器mapper接口上使用注解

MyBatis对于大部分的基础XML的映射器元素(、)提供了基于注解的配置项,然后在某一些情况下,基于注解的配置还不能支持一些基础XML的配置。
Mybatis提供了多种基于注解来支持不同的语句(statemant),如SELETCT、UPDATE、INSERT、DELETE。下面讲解这些注解该如何使用。

2.1@Insert

我们可以使用@insert注解来定义一个Insert映射语句:使用@insert返回SQL语句执行后数据库受影响的行数

@Insert("insert into student values (null,#{name},#{email},#{address},#{phone})")
public int insertStudent(Student s);

自动生成主键
我们可以使用@options注解的useGeneratedKeys和keyProperty属性让数据库产生auto_increament(自增长列的值),然后将生成的主键输入到对象的属性中!

@Insert("insert into student values (null,#{name},#{email},#{address},#{phone})")
@Options(useGeneratedKeys=true,keyProperty="id")
public int insertStudent(Student s);

测试:

	@Test
	public void testInsert(){
		Student s=new Student("小张", "[email protected]", "四川成都", "13378901010");
		int count = mapper.insertStudent(s);
		System.out.println(count>0?"成功":"失败");
		System.out.println("主键为:"+s.getId());
	}

有一些数据库,例如Oracle,并不支持AUTO_increament列属性,它使用序列来产生主键(SEQUENCE)的值!
我们可以使用注解来为任意SQL语句来指定主键值,作为主键列的值.假设我们有一个名为
STU_ID_SEQ的序列为主键生成自增

	@Insert("insert into student values (null,#{name},#{email},#{address},#{phone})")
	@SelectKey(statement="SELECT STUD_ID_SEQ.NEXTVAL FROM DUAL",keyProperty="id",resultType=Integer.class,before=true)
	public int insertStudent(Student s); 

这里使用@selectKey来生成主键值,并存储到了student对象的id属性上,由于设置的是before=true,该语句则将会在INSERT语句执行之前执行!

2.2 @update

我们可以使用@update注解来定义一个update映射语句:

@Update("update student set name=#{name},email=#{email},address=#{address},phone=#{phone} where id=#{id}")
public int updateStudent(Student s);

update语句返回SQL语句执行成功后数据库受影响的行数!

  • 测试
	@Test
	public void testUpdate(){
		Student s=new Student(4,"老张", "[email protected]", "四川XXX", "13378901010");
		int count = mapper.updateStudent(s);
		System.out.println(count>0?"成功":"失败");
	}

2.3 @delete

我们可以使用@delete注解来定义一个delete映射语句:

	@Delete("delete from student where id=#{id}")
	public int deleteStudent(int id);

delete语句返回SQL语句执行成功后数据库受影响的行数!

  • 测试
	@Test
	public void testDelete(){
		int count = mapper.deleteStudent(9);
		System.out.println(count>0?"成功":"失败");
	}

2.4 @select

我们可以使用@select注解来定义一个select映射语句:

  • 简单的select语句
	@Select("select * from student where id=#{id}")
	public Student findStudentById(int id);
	
	@Select("select * from student")
	public List<Student> findStudents();
  • 测试类
@Test
	public void testFindById(){
		Student s = mapper.findStudentById(8);
		System.out.println(s);
	}
	
	@Test
	public void testFindStudents(){
		List<Student> stus = mapper.findStudents();
		for (Student s : stus) {
			System.out.println(s);
		}
	}

2.5 结果映射

我们可以将查询结果通过别名或者是@result注解与对应JavaBean属性映射起来

	@Select("select * from student")
	@Results({
		@Result(id=true,column="id",property="id"),
		@Result(column="name",property="name"),
		@Result(column="email",property="email"),
		@Result(column="address",property="address"),
		@Result(column="phone",property="phone")
	})
	public List<Student> findAllStudents();
  • 测试类
	@Test
	public void testFindAllStudents(){
		List<Student> stus = mapper.findAllStudents();
		for (Student s : stus) {
			System.out.println(s);
		}
	}

MyBatis注解开发_第1张图片
如下代码,存在冗余:

@Select("select * from student where id=#{id}")
	@Results({
		@Result(id=true,column="id",property="id"),
		@Result(column="name",property="name"),
		@Result(column="email",property="email"),
		@Result(column="address",property="address"),
		@Result(column="phone",property="phone")
	})
	public Student findStudentById(int id);
	
	
	@Select("select * from student")
	@Results({
		@Result(id=true,column="id",property="id"),
		@Result(column="name",property="name"),
		@Result(column="email",property="email"),
		@Result(column="address",property="address"),
		@Result(column="phone",property="phone")
	})
	public List<Student> findAllStudents();

这里的@results内容完全相同,但是不得不重复一遍,这里有一个解决办法,我们可以创建一个Mapper文件,然后定义元素,使用注解@ResultMap来引用此.



<mapper namespace="com.mybatis.mapper.StudentMapper">

	<resultMap type="Student" id="stuMap">
		<id property="id" column="id" />
		<result property="name" column="name" />
		<result property="email" column="email" />
		<result property="address" column="address" />
		<result property="phone" column="phone" />
	resultMap>
	
mapper>

在StudentMapper中使用@ResultMap注解来引用StudentMapper.xml文件中的stuMap

	@Select("select * from student where id=#{id}")
	@ResultMap(value="com.mybatis.mapper.StudentMapper.stuMap")
	public Student findStudentById(int id);
	
	
	@Select("select * from student")
	@ResultMap(value="com.mybatis.mapper.StudentMapper.stuMap")
	public List<Student> findAllStudents();

3.关联映射

3.1一对一映射

MyBatis提供了@one注解来使用嵌套select语句加载一对一关联查询数据。

3.1.1需求

查询学生的时候关联查询该学生对应的身份证信息
MyBatis注解开发_第2张图片

3.1.2 Mapper接口文件

@Select("select * from card where id=#{id}")
	public Card findCardById(int id);
	
	
	@Select("select * from student where id=#{id}")
	@Results({
		@Result(id=true,column="id",property="id"),
		@Result(column="name",property="name"),
		@Result(column="email",property="email"),
		@Result(column="address",property="address"),
		@Result(column="phone",property="phone"),
		@Result(property="card",column="card_id",one=@One(select="com.mybatis.mapper.StudentMapper.findCardById"))
	})
	public Student selectStudentWithCard(int id);
  • 测试
	@Test
	public void testselectStudentWithCard(){
		Student s = mapper.selectStudentWithCard(1);
		System.out.println(s);
		Card c = s.getCard();
		System.out.println(c);
	}

也可以在StudentMapper.xml文件中进行配置,然后使用@ResultMap注解引用xml中的配置

<resultMap type="Student" id="stuMap">
		<id property="id" column="id" />
		<result property="name" column="name" />
		<result property="email" column="email" />
		<result property="phone" column="phone" />
		<result property="address" column="address" />
		<association property="card" resultMap="CardResultMap"/>
	resultMap>
	
	<resultMap type="Card" id="CardResultMap">
	   <id property="id" column="card_id"/>
	   <result property="number" column="number"/>
	   <result property="birthday" column="birthday"/>
	   <result property="mingzu" column="mingzu"/>
	resultMap>
@Select("select * from student,card WHERE student.card_id=card.id and student.id=#{id}")
@ResultMap("com.mybatis.mapper.StudentMapper.stuMap")
public Student selectStudentWithCard1(int id);
  • 测试
	@Test
	public void testselectStudentWithCard1(){
		Student s = mapper.selectStudentWithCard1(1);
		System.out.println(s);
		Card c = s.getCard();
		System.out.println(c);
	}

3.2 一对多映射

3.2.1 需求

查询教师关联查询该讲师的学生信息
MyBatis注解开发_第3张图片

3.2.2 Mapper接口文件

@Select("select * from student where teacher_id=#{id}")
	public List<Student> findStudentsByTeacherId(int id);

	@Select("select * from teacher where t_id=#{id}")
	@Results({
		@Result(id=true,column="t_id",property="id"),
		@Result(column="t_name",property="name"),
		@Result(column="t_age",property="age"),
		@Result(column="t_sex",property="sex"),
		@Result(property="students",column="t_id",many=@Many(select="com.mybatis.mapper.TeacherMapper.findStudentsByTeacherId"))
	})
	public Teacher findTeacherById(int id);

也可以在TeacherMapper.xml文件中进行配置,然后使用@ResultMap注解引用xml中的配置

<resultMap type="Teacher" id="teacherMap">
		<id property="id" column="t_id" />
		<result property="name" column="t_name" />
		<result property="age" column="t_age" />
		<result property="sex" column="t_sex" />
		<collection property="students" resultMap="StudentMap"/>
	resultMap>

	<resultMap type="Student" id="StudentMap">
		<id property="id" column="id" />
		<result property="name" column="name" />
		<result property="email" column="email" />
		<result property="phone" column="phone" />
		<result property="address" column="address" />
	resultMap>
	@Select("select * from teacher,student where teacher.t_id=student.teacher_id and teacher.t_id=#{id}")
	@ResultMap(value="com.mybatis.mapper.TeacherMapper.teacherMap")
	public Teacher findTeacherById1(int id);
  • 测试
@Test
	public void findTeacherById1(){
		Teacher t = mapper1.findTeacherById1(1);
		System.out.println(t);
		List<Student> students = t.getStudents();
		for (Student s : students) {
			System.out.println(s);
		}
	}

3.3 多对多映射

3.3.1 需求

查询课程的时候关联查询该课程下面所有的学生
MyBatis注解开发_第4张图片

3.3.2 Mapper接口文件

@Select("select * from student_course,student where student_course.student_id=student.id and student_course.course_id=#{id}")
	public List<Student> getStudentsByCourseId();

	@Select("select * from course where c_id=#{id}")
	@Results({
		@Result(id=true,column="c_id",property="id"),
		@Result(column="c_name",property="name"),
		@Result(column="c_time",property="time"),
		@Result(property="students",column="c_id",many=@Many(select="com.mybatis.mapper.CourseMapper.getStudentsByCourseId"))
	})
	public Course getCourseById(Integer id);
  • 测试
	@Test
	public void getCourseById(){
		Course c = mapper2.getCourseById(1);
		System.out.println(c);
		List<Student> students = c.getStudents();
		for (Student s : students) {
			System.out.println(s);
		}
	}

也可以在CourseMapper.xml文件中进行配置,然后使用@ResultMap注解引用xml中的配置

<resultMap type="Course" id="courseMap">
		<id column="c_id" property="id" />
		<result column="c_name" property="name" />
		<result column="c_time" property="time" />
		<collection property="students" resultMap="StudentMap" />
	resultMap>

	<resultMap type="Student" id="StudentMap">
		<id property="id" column="student_id" />
		<result property="name" column="name" />
		<result property="email" column="email" />
		<result property="phone" column="phone" />
		<result property="address" column="address" />
	resultMap>
	@Select("select * from course,student_course,student where student_course.student_id=student.id and student_course.course_id=course.c_id and course.c_id=#{id}")
	@ResultMap(value="com.mybatis.mapper.CourseMapper.courseMap")
	public Course getCourseById1(Integer id);
  • 测试
	@Test
	public void getCourseById1(){
		Course c = mapper2.getCourseById1(1);
		System.out.println(c);
		List<Student> students = c.getStudents();
		for (Student s : students) {
			System.out.println(s);
		}
	}

4.动态SQL

在这里插入图片描述

4.1@SelectProvider

Mybatis使用@SelectProvider注解来创建一个简单SELECT查询的映射语句

  • 创建一个TeacherDynaSqlProvider类,定义一个生成SQL的方法findTeacherByIdSql
public class TeacherDynaSqlProvider {
   
	public String findTeacherByIdSql(int t_id){
		return "select * from teacher where t_id=#{t_id}";
	}
}
  • 在mapper文件中国定义查询语句
	@SelectProvider(type=TeacherDynaSqlProvider.class,method="findTeacherByIdSql")
	@Results({
		@Result(id=true,column="t_id",property="id"),
		@Result(column="t_name",property="name"),
		@Result(column="t_age",property="age"),
		@Result(column="t_sex",property="sex")
	})
	public Teacher findTeacherById2(int t_id);

这里我们使用了@SelectProvider来指定一个类,并调用其中的方法,用来提供SQL语句
但是使用字符串拼接SQL是非常困难的,并且很容易出错!所以针对这种情况,Mybatis提供了一个SQL工具类,来构造SQL语句!

  • 示例:
public class TeacherDynaSqlProvider {

	public String findTeacherByIdSql() {
		SQL sql = new SQL();
		sql.SELECT("*");
		sql.FROM("teacher");
		sql.WHERE("t_id=#{t_id}");
		return sql.toString();
	}
}

MyBatis注解开发_第5张图片

  • 使用Map传入参数
	@SelectProvider(type=TeacherDynaSqlProvider.class,method="findTeachersSql")
	@Results({
		@Result(id=true,column="t_id",property="id"),
		@Result(column="t_name",property="name"),
		@Result(column="t_age",property="age"),
		@Result(column="t_sex",property="sex")
	})
	public List<Teacher> findTeachers(Map<String, Object> map);

	public String findTeachersSql(Map<String, Object> map){
		String name =(String) map.get("name");
		String sex =(String) map.get("sex");
		SQL sql = new SQL();
		sql.SELECT("*");
		sql.FROM(TABLE_NAME);
		if(name!=null){
			sql.WHERE("t_name like #{name}");
		}
		if(sex!=null){
			sql.WHERE("t_sex=#{sex}");
		}
		return sql.toString();
	}
  • 测试
	@Test
	public void testFindTeachers(){
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("name", "%张%");
		map.put("sex", "男");
		List<Teacher> teachers = mapper1.findTeachers(map);
		for (Teacher t : teachers) {
			System.out.println(t);
		}
	}

4.2 @InsertProvider

我们可以使用@InsertProvider来构建新增SQL语句

public String insertSql(Teacher t){
		SQL sql = new SQL();
		sql.INSERT_INTO(TABLE_NAME);
		if(t.getName()!=null){
			sql.VALUES("t_name", "#{name}");
		}
		if(t.getAge()!=null){
			sql.VALUES("t_age", "#{age}");
		}
		if(t.getSex()!=null){
			sql.VALUES("t_sex", "#{sex}");
		}
		return sql.toString();
	}
  • Mapper接口
	@InsertProvider(type=TeacherDynaSqlProvider.class,method="insertSql")
	public int insertTeacher(Teacher t);
  • 测试
	@Test
	public void testInsertTeacher(){
		Teacher t=new Teacher("八戒", 500, "男");
		int count = mapper1.insertTeacher(t);
		System.out.println("执行:"+count);
	}

4.3 @UpdateProvider

我们可以使用@UpdateProvider来构建更新SQL语句

public String updateSql(Teacher t){
		SQL sql = new SQL();
		sql.UPDATE(TABLE_NAME);
		if(t.getName()!=null){
			sql.SET("t_name=#{name}");
		}
		if(t.getAge()!=null){
			sql.SET("t_age=#{age}");
		}
		if(t.getSex()!=null){
			sql.SET("t_sex=#{sex}");
		}
		sql.WHERE("t_id=#{id}");
		return sql.toString();
	}
  • Mapper接口
	@UpdateProvider(type=TeacherDynaSqlProvider.class,method="updateSql")
	public int updateTeacher(Teacher t);
  • 测试
	@Test
	public void testUpdateTeacher(){
		Teacher t=new Teacher(3, "猪刚鬣", 34, "男");
		int count = mapper1.updateTeacher(t);
		System.out.println("执行:"+count);
	}

4.4 @DeleteProvider

我们可以使用@DeleteProvider来构建删除SQL语句

public String deleteSql(){
		SQL sql = new SQL();
		sql.DELETE_FROM(TABLE_NAME);
		sql.WHERE("t_id=#{id}");
		return sql.toString();
	}
  • Mapper接口
@DeleteProvider(type=TeacherDynaSqlProvider.class,method="deleteSql")
	public int deleteById(int id);
  • 测试
	@Test
	public void testDeleteTeacher() {
		int count = mapper1.deleteById(3);
		System.out.println("执行:" + count);
	}

5.总结

MyBatis注解的配置方式,其实在工作用应用不是很广泛。后期MyBati可以实现逆向工程,Mapper中自动生成,提高开发效率!

你可能感兴趣的:(MyBatis,MyBatis专题)