1. 程式人生 > >【MyBatis學習18】使用註解配置Mapper

【MyBatis學習18】使用註解配置Mapper

MyBatis支援使用註解來配置對映的sql語句,這樣可以省掉對映器xml檔案。

一、對映語句

1、insert 
比如入門例項中的:

public int insert(User user) throws Exception;
  • 1
  • 1
<insert id="insert"  parameterType="twm.mybatisdemo.pojo.User" useGeneratedKeys="true" keyProperty="id">
    <!-- 將插入資料的主鍵返回,返回到user物件中 -->
    insert into user (username,address,email) values (#{username},#{address},#{email})
</insert
>
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

改成註解來配置對映:

@Insert("insert into user (username,address,email) values (#{username},#{address},#{email})")
@Options(useGeneratedKeys = true, keyProperty = "id") 
public int insert(User user) throws Exception;
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

這裡使用@Insert註解來定義一個INSERT對映語句。 
並且使用@Options註解的userGeneratedKeys 和keyProperty

屬性,讓資料庫auto_increment生成的主鍵值,賦值到keyProperty標記的屬性id中

還有一種獲取主鍵的方法(Oracle要用SELECT SEQ.NEXTVAL FROM DUAL ,且order設為before)

<insert id="insert"  parameterType="twm.mybatisdemo.pojo.User" >
    <!-- 將插入資料的主鍵返回,返回到user物件中 -->
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"
>
select last_insert_id() </selectKey> insert into user (username,address,email) values (#{username},#{address},#{email}) </insert>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

相應的註解是:

@Insert("insert into user (username,address,email) values (#{username},#{address},#{email})")
@SelectKey(statement="select last_insert_id()",keyProperty="id", resultType=int.class, before=true)
public int insert(User user) throws Exception;
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

2、select

@Select("select * from user where id=#{id}")
public User selectById(int id) throws Exception;
  • 1
  • 2
  • 1
  • 2

返回的是一個User物件,因此如果select語句返回多行記錄,就會出現TooManyResultsException異常。

3、update

@Update("update user set username=#{username},address=#{address},email=#{email} where id=#{id}")
public int update(User user) throws Exception;
  • 1
  • 2
  • 1
  • 2

4、delete

@Delete("delete from user where id=#{id}")
public int delete(int id) throws Exception;
  • 1
  • 2
  • 1
  • 2

二、結果對映

在xml配置檔案中,將查詢結果和JavaBean屬性對映起來的標籤是<resultMap>。對應的是@Results註解

@Select("select * from user")
@Results({ @Result(id = true, column = "id", property = "id"),
        @Result(column = "username", property = "user_name"),
        @Result(column = "city", property = "city") })
public List<User> selectAll() throws Exception;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

@Results註解沒辦法複用。譬如我們的public User selectById(int id) throws Exception也要用到同樣的@Results註解,但還是要重新寫一個一模一樣的@Results

@Select("select * from user where id=#{id}")
@Results({ @Result(id = true, column = "id", property = "id"),
        @Result(column = "username", property = "user_name"),
        @Result(column = "city", property = "city") })
public User selectById(int id) throws Exception;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

如果要想使用可以複用的對映器,那麼就使用@ResultMap註解。該註解依賴一個xml配置檔案。 
在介面檔案同目錄下新建一個userMapper.xml檔案,並定義一個名為userMap的resultMap。

<mapper namespace="twm.mybatisdemo.mapper.UserMapper">
    <!-- 自定義返回結果集 -->
    <resultMap id="userMap" type="twm.mybatisdemo.pojo.User">
        <id column="id" property="id" jdbcType="INTEGER" />
        <result property="user_name" column="username"></result>
        <result property="city" column="city"></result>
    </resultMap>
</mapper>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在userMapper.Java中,使用@ResultMap引用名為userMap的resultMap,實現複用。

@Select("select * from user where id=#{id}")  
@ResultMap("twm.mybatisdemo.mapper.UserMapper.userMap")  
public User selectById(int id) throws Exception;

@Select("select * from user")  
@ResultMap("twm.mybatisdemo.mapper.UserMapper.userMap")  
public List<User> selectAll() throws Exception;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

三、關聯關係

1、一對一關係 
MyBatis提供了@One註解來配合@Result註解,從而實現一對一關聯查詢資料的載入。 
比如所有user物件都有個配偶資訊spouse(本例中配偶本身也是一個user物件)

@Select("select * from user")
@Results({ @Result(id = true, column = "id", property = "id"),
        @Result(column = "username", property = "user_name"),
        @Result(column = "city", property = "city"),
        @Result(column = "account_id", property = "account",one = @One(select = "twm.mybatisdemo.mapper.AccountMapper.selectById")) })
public List<User> selectAll() throws Exception;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在這裡column = "account_id"指定了向twm.mybatisdemo.mapper.AccountMapper.selectById方法傳遞的引數。如果@OneSELECT查詢返回了多行結果,則會丟擲TooManyResultsException異常。

呼叫:

UserMapper userMapper =sqlSession.getMapper(UserMapper.class);  
List<User> userlist = userMapper.selectAll();  
System.out.println(userlist[0].getAccount().getBalance()); 
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

如果結果對映使用的是xml檔案,那麼可以association 來配置對映:

<mapper namespace="twm.mybatisdemo.mapper.UserMapper">
    <!-- 自定義返回結果集 -->
    <resultMap id="userMapWithAccount" type="twm.mybatisdemo.pojo.User">
        <id column="id" property="id" jdbcType="INTEGER" />
        <result property="user_name" column="username"></result>
        <result property="city" column="city"></result>
        <association property="account" javaType="Account" column="account_id" 
            select="twm.mybatisdemo.mapper.AccountMapper.selectById" />
    </resultMap>
</mapper>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

介面如下:

@Select("select * from user")
@ResultMap("twm.mybatisdemo.mapper.UserMapper.userMapWithAccount")
public List<User> selectAll() throws Exception;
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

2、一對多關係 
MyBatis提供了@Many註解來配合@Result註解,從而實現一對多關聯查詢資料的載入。 
現在讓我們看一下如何使用@Many註解獲取一個講師及其教授課程列表資訊:

public interface TutorMapper
{
    @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.mybatis3.
        mappers.TutorMapper.findAddressById")),
        @Result(property = "courses", column = "tutor_id",
        many = @Many(select = "com.mybatis3.mappers.TutorMapper.
        findCoursesByTutorId"))
    })
    Tutor findTutorById(int tutorId);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

同樣也可以採用配置xml中配置resultMaps的方式

<mapper namespace="com.mybatis3.mappers.TutorMapper">
    <resultMap type="Course" id="CourseResult">
        <id 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" />
    </resultMap>
    <resultMap type="Tutor" id="TutorResult">
        <id column="tutor_id" property="tutorId" />
        <result column="tutor_name" property="name" />
        <result column="email" property="email" />
        <collection property="courses" resultMap="CourseResult" />
    </resultMap>
</mapper>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
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}")
    @ResultMap("com.mybatis3.mappers.TutorMapper.TutorResult")
    Tutor selectTutorById(int tutorId);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

四、動態SQL

MyBatis提供了各種註解如@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider,來幫助構建動態SQL語句,然後讓MyBatis執行這些SQL語句。

這裡重點用@SelectProvider舉例:

建立一個TutorDynaSqlProvider.java類,以及findTutorByIdSql()方法,如下所示:

package com.mybatis3.sqlproviders;
import org.apache.ibatis.jdbc.SQL;
public class TutorDynaSqlProvider
{
    public String findTutorByIdSql(int tutorId)
    {
        return "SELECT TUTOR_ID AS tutorId, NAME, EMAIL FROM TUTORS
               WHERE TUTOR_ID=" + tutorId;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在TutorMapper.java介面中建立一個對映語句,如下:

@SelectProvider(type=TutorDynaSqlProvider.class, method="findTutorByIdSql")  
Tutor findTutorById(int tutorId);  
  • 1
  • 2
  • 1
  • 2