最近在讀劉增輝老師所著的《MyBatis從入門到精通》一書,頗有收穫,因而將本身學習的過程以博客形式輸出,若有錯誤,歡迎指正,如幫助到你,不勝榮幸!java
假設如今有個需求:根據id查詢角色信息。使用註解方式該如何實現呢?git
首先,在接口SysRoleMappper中添加以下方法:github
@Select({"SELECT id,role_name roleName,enabled,create_by createBy,create_time createTime ","FROM sys_role ","WHERE id = #{id}"}) SysRole selectById(Long id);
上面的代碼也能夠寫成以下格式:sql
@Select({"SELECT id,role_name roleName,enabled,create_by createBy,create_time createTime FROM sys_role WHERE id = #{id}"}) SysRole selectById(Long id);
以上2種方式都是傳遞字符串數組的形式,咱們還能夠用直接傳遞字符串的形式:數據庫
@Select("SELECT id,role_name roleName,enabled,create_by createBy,create_time createTime FROM sys_role WHERE id = #{id}") SysRole selectById(Long id);
使用註解方式一樣須要考慮表字段和Java屬性字段映射的問題,使用註解方式主要有3種方式來實現。apache
第1種方式是經過Sql語句設置別名,上面的代碼就用的是這種方式。數組
打開src/main/resources目錄下咱們以前新建的mybatis-config.xml文件,添加以下配置:session
<settings> <!--其餘配置--> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
該配置打開後,MyBatis會按照「下劃線轉駝峯「規則自動映射,即將數據庫列role_name自動轉換爲屬性roleName。mybatis
此時,上面的代碼能夠修改成:app
@Select("SELECT id,role_name,enabled,create_by,create_time FROM sys_role WHERE id = #{id}") SysRole selectById(Long id);
雖然也能夠寫爲以下格式,可是不推薦這麼使用:
@Select("SELECT * FROM sys_role WHERE id = #{id}") SysRole selectById(Long id);
在xml中,咱們使用過resultMap來配置映射:
<resultMap id="sysUserMap" type="com.zwwhnly.mybatisaction.model.SysUser"> <id property="id" column="id"/> <result property="userName" column="user_name"/> <result property="userPassword" column="user_password"/> <result property="userEmail" column="user_email"/> <result property="userInfo" column="user_info"/> <result property="headImg" column="head_img" jdbcType="BLOB"/> <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> </resultMap>
在註解方式中,有一個對應的註解@Results來配置映射:
@Results({ @Result(property = "id", column = "id", id = true), @Result(property = "roleName", column = "role_name"), @Result(property = "enabled", column = "enabled"), @Result(property = "createBy", column = "create_by"), @Result(property = "createTime", column = "create_time") }) @Select("SELECT id,role_name,enabled,create_by,create_time FROM sys_role WHERE id = #{id}") SysRole selectById2(Long id);
代碼簡單講解:
1)@Results註解對應着xml中的resultMap標籤
2)@Result對應着xml中的result標籤
3)@Result(property = "id", column = "id", id = true)
對應着xml中的<id property="id" column="id"/>
也許有人會問,我在xml中,爲resultMap設置了一個id,這樣我就能複用該resultMap了,在註解方式中,支持嗎?
帶着這個疑問,讓咱們來試着修改下代碼:
@Results(id = "roleResultMap", value = { @Result(property = "id", column = "id", id = true), @Result(property = "roleName", column = "role_name"), @Result(property = "enabled", column = "enabled"), @Result(property = "createBy", column = "create_by"), @Result(property = "createTime", column = "create_time") }) @Select("SELECT id,role_name,enabled,create_by,create_time FROM sys_role WHERE id = #{id}") SysRole selectById2(Long id);
結果發現代碼編譯錯誤,找不到id屬性。
按下Ctrl+B,發現@Results的源碼以下:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Results { Result[] value() default {}; }
從源碼咱們能夠發現,這個註解沒有id屬性,難道咱們每一個方法上都要加上重複的映射嗎?
答案固然是否認的,不過在MyBatis 3.3.0及之前的版本中,註解定義的@Results不能共用,須要在每個方法上都寫一遍。可是從MyBatis 3.3.1版本開始,@Results註解增長了一個id屬性,設置了id屬性後,就能夠經過id屬性引用同一個@Results配置了。
看過以前幾篇博客的讀者可能知道,咱們的MyBatis 恰好使用的是3.3.0版本,因此恰好不支持設置id屬性,哈哈。
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.3.0</version> </dependency>
修改MyBatis的版本爲3.3.1(若是沒有設置自動導入變化的話,須要手動點下Import Changes):
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.3.1</version> </dependency>
這時會發現,上面本來編譯報錯的代碼能夠編譯經過了。
此時@Results的源碼以下,相比於以前的代碼,增長了id屬性:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Results { String id() default ""; Result[] value() default {}; }
那如何引用這個@Results註解呢?請看以下代碼:
@ResultMap("roleResultMap") @Select("SELECT * FROM sys_role") List<SysRole> selectAll();
說明:當配合XML方式使用的時候,這裏引用的id值還能夠是XML中resultMap元素的id屬性值。
爲了使篇幅不至於過長,這裏再也不貼出這3個方法的單元測試代碼和輸出日誌,相信看過前幾篇博客的讀者已經能夠本身寫出單元測試代碼了,也能夠參考文末的源碼地址下載下源碼。
和XML中的使用方式幾乎同樣,代碼以下:
@Insert({"INSERT INTO sys_role(id, role_name, enabled, create_by, create_time) ", "VALUES (#{id},#{roleName},#{enabled},#{createBy},#{createTime,jdbcType=TIMESTAMP})"}) int insert(SysRole sysRole);
若是須要返回數據庫的自增主鍵,代碼以下:
@Insert({"INSERT INTO sys_role(role_name, enabled, create_by, create_time) ", "VALUES (#{roleName},#{enabled},#{createBy},#{createTime,jdbcType=TIMESTAMP})"}) @Options(useGeneratedKeys = true, keyProperty = "id") int insertUseGeneratedKeys(SysRole sysRole);
和XML中的使用方式差很少,@Options(useGeneratedKeys = true, keyProperty = "id")
等價於XML中的useGeneratedKeys="true" keyProperty="id"
。
在以前的博客中,咱們知道selectKey既支持主鍵自增的數據庫,好比MySql,也支持主鍵不自增的數據庫,如Oracle,在XML中的寫法是這樣的:
<selectKey keyColumn="id" resultType="long" keyProperty="id" order="AFTER"> SELECT LAST_INSERT_ID() </selectKey>
那麼使用註解方式該如何實現呢?代碼以下所示:
@Insert({"INSERT INTO sys_role(role_name, enabled, create_by, create_time) ", "VALUES (#{roleName},#{enabled},#{createBy},#{createTime,jdbcType=TIMESTAMP})"}) @SelectKey(statement = "SELECT LAST_INSERT_ID()", keyColumn = "id", keyProperty = "id", resultType = Long.class, before = false) int insertUseSelectKey(SysRole sysRole);
before = false至關於XML中的order="AFTRE",這是MySql數據庫的配置。
before = true至關於XML中的order="BEFORE",這是Oracle數據庫的配置。
注意事項:不一樣的數據庫statement的值會不一樣,上面中的值適用於MySql數據庫,使用其餘類型的數據庫時要注意修改。
和XML中的使用方式幾乎同樣,代碼以下:
@Update({"UPDATE sys_role ", "SET role_name = #{roleName},enabled = #{enabled},create_by=#{createBy}, ", "create_time=#{createTime,jdbcType=TIMESTAMP} ", " WHERE id=#{id}"}) int updateById(SysRole sysRole);
和XML中的使用方式幾乎同樣,代碼以下:
@Delete("DELETE FROM sys_role WHERE id = #{id}") int deleteById(Long id);
MyBatis提供了4種Provider註解,分別是@SelectProvider、@InsertProvider、@UpdateProvider和@DeleteProvider。
咱們以@SelectProvider爲例瞭解下Provider註解的使用方法。
首先在com.zwwhnly.mybatisaction.mapper包下新建以下類:
package com.zwwhnly.mybatisaction.mapper; import org.apache.ibatis.jdbc.SQL; public class SysPrivilegeProvider { public String selectById(final Long id) { return new SQL() { { SELECT("id,privilege_name,privilege_url"); FROM("sys_privilege"); WHERE("id = #{id}"); } }.toString(); } }
以上代碼也能夠寫成以下方式:
public String selectById(final Long id) { return "SELECT id,privilege_name,privilege_url FROM sys_privilege WHERE id = #{id}"; }
而後在接口SysPrivilegeProvider中添加以下方法:
@SelectProvider(type = SysPrivilegeProvider.class, method = "selectById") SysPrivilege selectById(Long id);
最後在src/test/java下的com.zwwhnly.mybatisaction.mapper包下新建測試類SysPrivilegeMapperTest:
package com.zwwhnly.mybatisaction.mapper; import com.zwwhnly.mybatisaction.model.SysPrivilege; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; public class SysPrivilegeMapperTest extends BaseMapperTest { @Test public void testSelectById() { SqlSession sqlSession = getSqlSession(); try { SysPrivilegeMapper sysPrivilegeMapper = sqlSession.getMapper(SysPrivilegeMapper.class); SysPrivilege sysPrivilege = sysPrivilegeMapper.selectById(1L); Assert.assertNotNull(sysPrivilege); Assert.assertEquals("用戶管理", sysPrivilege.getPrivilegeName()); } finally { sqlSession.close(); } } }
運行測試代碼,測試經過,輸出日誌以下:
DEBUG [main] - ==> Preparing: SELECT id,privilege_name,privilege_url FROM sys_privilege WHERE (id = ?)
DEBUG [main] - ==> Parameters: 1(Long)TRACE [main] - <== Columns: id, privilege_name, privilege_url
TRACE [main] - <== Row: 1, 用戶管理, /users
DEBUG [main] - <== Total: 1
源碼地址:https://github.com/zwwhnly/mybatis-action.git,歡迎下載。
劉增輝《MyBatis從入門到精通》