上一章中,我们看到了映射器Mapper XML的使用。其实MyBatis也支持使用注解的方式来进行SQL的映射,只不过这中方式使用更少一些。本章将涵盖以下的话题:
MyBatis对于大部分的基础XML的映射器元素(、)提供了基于注解的配置项,然后在某一些情况下,基于注解的配置还不能支持一些基础XML的配置。
Mybatis提供了多种基于注解来支持不同的语句(statemant),如SELETCT、UPDATE、INSERT、DELETE。下面讲解这些注解该如何使用。
我们可以使用@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语句执行之前执行!
我们可以使用@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?"成功":"失败");
}
我们可以使用@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?"成功":"失败");
}
我们可以使用@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);
}
}
我们可以将查询结果通过别名或者是@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);
}
}
@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();
MyBatis提供了@one注解来使用嵌套select语句加载一对一关联查询数据。
@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);
}
@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);
}
}
@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);
}
}
Mybatis使用@SelectProvider注解来创建一个简单SELECT查询的映射语句
public class TeacherDynaSqlProvider {
public String findTeacherByIdSql(int t_id){
return "select * from teacher where t_id=#{t_id}";
}
}
@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();
}
}
@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);
}
}
我们可以使用@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();
}
@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);
}
我们可以使用@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();
}
@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);
}
我们可以使用@DeleteProvider来构建删除SQL语句
public String deleteSql(){
SQL sql = new SQL();
sql.DELETE_FROM(TABLE_NAME);
sql.WHERE("t_id=#{id}");
return sql.toString();
}
@DeleteProvider(type=TeacherDynaSqlProvider.class,method="deleteSql")
public int deleteById(int id);
@Test
public void testDeleteTeacher() {
int count = mapper1.deleteById(3);
System.out.println("执行:" + count);
}
MyBatis注解的配置方式,其实在工作用应用不是很广泛。后期MyBati可以实现逆向工程,Mapper中自动生成,提高开发效率!