Mybatis学习笔记-五、MyBatis中的注解

五、MyBatis中的注解

之前我们都是在映射器MapperXML配置文件中配置映射语句的。除此之外MyBatis也支持使用注解来配置映射语句。当我们使用基于注解的映射器接口时,我们不再需要在XML配置文件中配置了。如果你愿意,你也可以同时使用基于XML和基于注解的映射语句。

5.1 在映射器Mapper接口上使用注解

MyBatis对于大部分的基于XML的映射器元素(包括,)提供了对应的基于注解的配置项。然而在某些情况下,基于注解配置还不能支持基于XML的一些元素。

5.2 映射语句

MyBatis提供了多种注解来支持不同类型的语句如:SELECT,INSERT,UPDATE,DELETE。

5.2.1 @Insert

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

package com.briup.mappers; 
public interface StudentMapper{ 

	@Insert("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,ADDR_ID, PHONE) 
			VALUES(#{studId},#{name},#{email},#{address.addr Id},#{phone})") 
	int insertStudent(Student student); 

} 

自动生成主键

可以使用 @Options注解的userGeneratedKeys和keyProperty属性让数据库产生 auto_increment(自增长)列的值,然后将生成的值设置到输入参数对象的属性中。

@Insert("INSERT INTO STUDENTS(NAME,EMAIL,ADDR_ID, PHONE) 
		VALUES(#{name},#{email},#{address.addr Id},#{phone})") 
@Options(useGeneratedKeys = true, keyProperty = "studId") 
int insertStudent(Student student); 

这里STUD_ID列值将会通过MySQL数据库自动生成。并且生成的值将会被设置到student对象的studId属性中。

StudentMapper mapper = sqlSession.get Mapper(Student Mapper.class); 
mapper.insertStudent(student); 
int studentId = student.getStudId(); =

有一些数据库如Oracle,并不支持AUTO_INCREMENT列属性,它使用序列(SEQUENCE)来产生主键的值。
我们可以使用 @SelectKey注解来为任意SQL语句来指定主键值,作为主键列的值。假设我们有一个名为STUD_ID_SEQ的序列来生成STUD_ID主键值。

@Insert("INSERT INTO STUDENTS(STUD_ID,NAME,EMAIL,ADDR_ID, PHONE)  
VALUES(#{studId},#{name},#{email},#{address.addrId},#{phone})") 
@SelectKey(statement="SELECT STUD_ID_SEQ.NEXTVAL FROM DUAL",  
keyProperty="studId", resultType=int.class, before=true) 
int insertStudent(Student student); 

这里我们使用了 @Select Key来生成主键值,并且存储到了student对象的studId属性上。由于我们设置了before=true,该语句将会在执行INSERT语句之前执行。如果你使用序列作为触发器来设置主键值,我们可以在INSERT语句执行后,从sequence_name.currval获取数据库产生的主键值。

@Insert("INSERT INTO STUDENTS(NAME,EMAIL,ADDR_ID, PHONE)  
VALUES(#{name},#{email},#{address.addrId},#{phone})") 
@SelectKey(statement="SELECT STUD_ID_SEQ.CURRVAL FROM DUAL",  
keyProperty="studId", resultType=int.class, before=false) 
int insertStudent(Student student); 

5.2.2 @Update

我们可以使用 @Update注解来定义一个UPDATE映射语句,如下所示:

@Update("UPDATE STUDENTS SET NAME=#{name}, EMAIL=#{email},  
PHONE=#{phone} WHERE STUD_ID=#{studId}") 
int updateStudent(Student student); 
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); 
int noOfRowsUpdated = mapper.updateStudent(student); 

5.2.3 @Delete

我们可以使用 @Delete注解来定义一个DELETE映射语句,如下所示:

@Delete("DELETE FROM STUDENTS WHERE STUD_ID=#{studId}") 
int deleteStudent(int studId);

5.2.4 @Select

我们可以使用 @Select注解来定义一个SELECT映射语句。

package com.briup.mappers; 
public interface StudentMapper{ 
	@Select("SELECT STUD_ID AS STUDID, NAME, EMAIL, PHONE FROM 
			STUDENTS WHERE STUD_ID=#{studId}") 
	Student findStudentById(Integer studId); 
} 

为了将列名和Student bean属性名匹配,我们为stud_id起了一个studId的别名。如果返回了多行结果,将抛出TooManyResultsException异常。

5.3 结果映射

我们可以将查询结果通过别名或者是 @Results注解与Java Bean属性映射起来。

package com.briup.mappers; 
public interface StudentMapper{ 
	@Select("SELECT * FROM STUDENTS") 
	@Results( 
	{ 
		@Result(id = true, column = "stud_id", property = "studId"), 
		@Result(column = "name", property = "name"), 
		@Result(column = "email", property = "email"), 
		@Result(column = "addr_id", property = "address.addrId") 
	}) 
	List<Student> findAllStudents(); 
} 

注意:
@Results注解和映射器XML配置文件元素 对应。然而,My Batis3.2.2不能为 @Results注解赋予一个ID。所以,不像元素,我们不应在不同的映射语句中重用 @Results声明。这意味着即使 @Results注解完全相同,我们也需要(在不同的映射接口中)重复 @Results声明。

例如,看下面的 findStudentById()和 findAllStudents()方法:

@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}") 
@Results( 
{ 
	@Result(id = true, column = "stud_id", property = "studId"), 
	@Result(column = "name", property = "name"), 
	@Result(column = "email", property = "email"), 
	@Result(column = "addr_id", property = "address.addrId") 
}) 
Student findStudentById(int studId);

@Select("SELECT * FROM STUDENTS") 
@Results( 
{ 
	@Result(id = true, column = "stud_id", property = "studId"), 
	@Result(column = "name", property = "name"), 
	@Result(column = "email", property = "email"), 
	@Result(column = "addr_id", property = "address.addrId") 
}) 
List<Student> findAllStudents(); 

这里两个语句的 @Results配置完全相同,但是必须得重复它。这里有一个解决方法。我们可以创建一个映射器Mapper配置文件,然后配置元素,然后使用 @ResultMap注解引用此。 在StudentMapper.xml中定义一个ID为StudentResult的。

xml配置:

<mapper namespace="com.briup.mappers.StudentMapper"> 
  <resultMap type="Student" id="StudentResult"> 
	<id property="studId" column="stud_id" /> 
	<result property="name" column="name" /> 
	<result property="email" column="email" /> 
	<result property="phone" column="phone" /> 
  </resultMap> 
</mapper> 

在StudentMapper.java中,使用 @Result Map引用名为StudentResult的resultMap:

	@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId}") 
	@ResultMap("com.briup.mappers.StudentMapper.StudentResult") 
	Student findStudentById(int stud Id); 

	@Select("SELECT * FROM STUDENTS") 
	@ResultMap("com.briup.mappers.StudentMapper.StudentResult") 
	List<Student> findAllStudents(); 
}

5.4 一对一映射

MyBatis提供了 @One注解来使用嵌套select语句(Nested-Select)加载一对一关联查询数据。让我们看看怎样使用 @One注解获取学生及其地址信息

public interface StudentMapper{ 
	@Select("SELECT ADDR_ID AS ADDRID, STREET, CITY, STATE, ZIP, COUNTRY FROM ADDRESSES WHERE ADDR_ID=#{id}") 
	Address findAddressById(int id); 

	@Select("SELECT * FROM STUDENTS WHERE STUD_ID=#{studId} ") 
	@Results( 
	{ 
		@Result(id = true, column = "stud_id", property = "studId"), 
		@Result(column = "name", property = "name"), 
		@Result(column = "email", property = "email"), 
		@Result(property = "address", column = "addr_id", 
		one = @One(select = "com.briup.mappers.Student Mapper.findAddressById")) 
	}) 
	Student selectStudentWithAddress(int studId); 
} 

这里我们使用了 @One注解的select属性来指定一个使用了完全限定名的方法上,该方法会返回一个Address对象。使用column=”addr_id”,则STUEDNTS表中列addr_id的值将会作为输入参数传递给find Address By Id()方法。如果 @One SELECT查询返回了多行结果,则会抛出TooManyResultsException异常。

int studId = 1; 
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); 
Student student = studentMapper.selectStudentWithAddress(studId); 
System.out.println("Student :"+student); 
System.out.println("Address :"+student.getAddress()); 

我们可以通过基于XML的映射器配置,使用嵌套结果ResultMap来加载一对一关联的查询。而MyBatis3.2.2 版本,并没有对应的注解支持。但是我们可以在映射器Mapper配置文件中配置并且使用 @ResultMap注解来引用它。
在StudentMapper.xml中配置,如下所示:

<mapper namespace="com.briup.mappers.StudentMapper"> 
  <resultMap type="Address" id="AddressResult"> 
	<id property="addrId" column="addr_id" /> 
	<result property="street" column="street" /> 
	<result property="city" column="city" /> 
	<result property="state" column="state" /> 
	<result property="zip" column="zip" /> 
	<result property="country" column="country" /> 
  </resultMap> 
  <resultMap type="Student" id="StudentWithAddressResult"> 
	<id property="studId" column="stud_id" /> 
	<result property="name" column="name" /> 
	<result property="email" column="email" /> 
	<association property="address" resultMap="AddressResult" /> 
  </resultMap> 
</mapper> 
public interface StudentMapper{ 
	@Select("select stud_id, name, email, a.addr_id, street, city, state, zip, country" + " FROM students s left outer join addresses a on s.addr_id=a.addr_id" + " where stud_id=#{studId} ") 
	@ResultMap("com.briup.mappers.StudentMapper.StudentWithAddressResult") 
	Student selectStudentWithAddress(int id); 
} 

5.5 一对多映射

MyBatis提供了 @Many注解,用来使用嵌套Select语句加载一对多关联查询。现在让我们看一下如何使用 @Many注解获取一个讲师及其教授课程列表信息:

public interface TutorMapper{ 
@Select("select addr_id as addrId, street, city, state, zip, 
		country from addresses where addr_id=#{id}") 
Address findAddressById(int id); 
@Select("select * from courses where tutor_id=#{tutorId}") 
@Results( 
{ 
	@Result(id = true, column = "course_id", property = "courseId"), 
	@Result(column = "name", property = "name"), 
	@Result(column = "description", property = "description"), 
	@Result(column = "start_date" property = "startDate"), 
	@Result(column = "end_date" property = "endDate") 
}) 
List<Course> findCoursesByTutorId(int tutorId); 

@Select("SELECT tutor_id, name as tutor_name, email, addr_id 
		FROM tutors where tutor_id=#{tutorId}") 
@Results( 
{ 
	@Result(id = true, column = "tutor_id", property = "tutorId"), 
	@Result(column = "tutor_name", property = "name"), 
	@Result(column = "email", property = "email"), 
	@Result(property = "address", column = "addr_id", 
	one = @One(select = "com.briup.mappers.Tutor Mapper.findAddressById")), 
	@Result(property = "courses", column = "tutor_id", 
	many = @Many(select = "com.briup.mappers.Tutor Mapper.findCoursesByTutorId")) 
}) 
Tutor findTutorById(int tutorId); 
} 

这里我们使用了 @Many注解的select属性来指向一个完全限定名称的方法,该方法将返回一个 List对象。使用column=”tutor_id”,TUTORS表中的tutor_id列值将会作为输入参数传递给find Courses By Tutor Id()方法。
之前我们使用过嵌套结果ResultMap来加载一对多关联的查询。而MyBatis3.2.2版本,并没有对应的注解支持。但是我们可以在映射器Mapper配置文件中配置并且使用 @ResultMap注解来引用它。

在TutorMapper.xml中配置,如下所示:

<mapper namespace="com.briup.mappers.Tutor Mapper"> 
  <resultMap type="Address" id="AddressResult"> 
	<id property="addrId" column="addr_id" /> 
	<result property="street" column="street" /> 
	<result property="city" column="city" /> 
	<result property="state" column="state" /> 
	<result property="zip" column="zip" /> 
	<result property="country" column="country" /> 
  </resultMap> 
  <resultMap type="Course" id="CourseResult"> 
	<id column="course_id" property="course Id" /> 
	<result column="name" property="name" /> 
	<result column="description" property="description" /> 
	<result column="start_date" property="startDate" /> 
	<result column="end_date" property="endDate" /> 
  </resultMap> 
  <resultMap type="Tutor" id="TutorResult"> 
	<id column="tutor_id" property="tutorId" /> 
	<result column="tutor_name" property="name" /> 
	<result column="email" property="email" /> 
	<association property="address" result Map="AddressResult" /> 
	<collection property="courses" result Map="CourseResult" /> 
  </resultMap> 
</mapper> 
public interface TutorMapper{ 
	@Select("SELECT T.TUTOR_ID, T.NAME AS TUTOR_NAME, EMAIL, 
			A.ADDR_ID, STREET, CITY, STATE, ZIP, COUNTRY, COURSE_ID, C.NAME, 
			DESCRIPTION, START_DATE, END_DATE  FROM TUTORS T LEFT OUTER 
			JOIN ADDRESSES A ON T.ADDR_ID=A.ADDR_ID LEFT OUTER JOIN COURSES 
			C ON T.TUTOR_ID=C.TUTOR_ID WHERE T.TUTOR_ID=#{tutorId}") 
	@Result Map("com.briup.mappers.TutorMapper.TutorResult") 
	Tutor selectTutorById(int tutorId); 
} 

``
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值