MyBatis 的真正強(qiáng)大之處在于它的映射語句,這也是它的魔力所在坑赡。由于它的映射語句異
常強(qiáng)大烙如,映射器的 XML 文件就顯得相對簡單。
MyBatis 3.0 相比 2.0 版本的一個(gè)最大變化毅否,就是支持使用接口來調(diào)用方法亚铁。
以前使用 SqlSession 通過命名空間調(diào)用 MyBatis 方法時(shí),首先需要用到命名空間和方法
id 組成的字符串來調(diào)用相應(yīng)的方法 螟加。 當(dāng)參數(shù)多于 1 個(gè)的時(shí)候徘溢,需要將所有參數(shù)放到一個(gè) Map
對象中 。 通過 Map 傳遞多個(gè)參數(shù)捆探,使用起來很不方便然爆,而且還無法避免很多重復(fù)的代碼。
使用接口調(diào)用方式就會方便很多黍图, MyBatis 使用 Java 的動態(tài)代理可以直接通過接口來調(diào)
用 相應(yīng) 的方法曾雕,不需要提供接口的實(shí)現(xiàn)類,更不需要在實(shí)現(xiàn)類中使用 SqlSess 工∞以通過
命名空 間間接調(diào)用 助被。 另外剖张,當(dāng)有多個(gè)參數(shù)的時(shí)候切诀,通過參數(shù)注解@ Par am 設(shè)置參數(shù)的名字省
去了 手動構(gòu)造 Map 參數(shù)的過程,尤其在 Spring 中使用的時(shí)候搔弄,可以配置為自動掃描所有的
接口類 趾牧,直接將接口注入需要用到的地方。
mapper文件示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cnpiec.ireader.dao.GetBookDataDao">
<insert id="batchInsertBook" parameterType="Book">
INSERT INTO BOOK (BOOKID,NAME,PARTNERNAME) VALUES
<foreach collection="list" item="book" separator=",">
(#{book.bookId}, #{book.name}, #{book.partnerName})
</foreach>
</insert>
</mapper>
需要注意的是<mapper>根標(biāo)簽的 name space 屬性肯污。當(dāng) Mapper 接口和 XML 文件關(guān)聯(lián)的
時(shí)候,命名空間口amespace 的值就需要配置成接口的全限定名稱吨枉,例如 UserMapper 接口對
應(yīng)的 tk. mybatis . simple .mapper . UserMapper, MyBatis 內(nèi)部就是通過這個(gè)值將接口和
XML 關(guān)聯(lián)起來的蹦渣。
mybati s-config.xml 配置文件中的 mappers 元素中配置所有的 mapper ,部分配置代碼如下 貌亭。
<mappers>
<mapper resource=” tk/mybatis/simple/mapper/CountryMapper.xml ” / >
<mapper resource=” tk/mybatis/simple/mapper/UserMapper . xml ” / >
<mapper resource=” tk/mybatis/simple/mapper/RoleMapper.xml ” />
<mapper resource=” tk/mybatis/simple/mapper/PrivilegeMapper . xml ” />
<mapper resource=” tk/mybatis/simple/mapper/UserRoleMapper . xml ” />
<mapper resource=” tk/mybatis/simple/mapper / RolePrivilegeMapper.xml ” />
</mappers>
更簡單的配置方式柬唯,代碼如下
<mappers>
<package name= ” tk.mybatis . simple . mapper ” />
</mappers>
這種配置方式會先查找 tk.mybatis.simple . mapper 包下所有的接口,循環(huán)對接口進(jìn)行
如下操作圃庭。
這種配置方式會先查找 tk.mybatis.simple . mapper 包下所有的接口锄奢,循環(huán)對接口進(jìn)行
如下操作。
- 判斷接口對應(yīng)的命名 空 間是否己經(jīng)存在剧腻,如果不存在就拋出異常拘央,存在就繼續(xù)進(jìn)行接下
來的操作。 - 加載接口對應(yīng)的卻也映射文件 书在, 將接口全限定名轉(zhuǎn)換為路徑 灰伟, 例如 , 將接口
tk.mybatis.simple.mapper.UserMapper 轉(zhuǎn)換為 tk/mybati s/simple/mapper/UserMapper.xml,
搜索以.xml 為后綴搜索 XML 資源儒旬,如果找到就解析 XML 栏账。 - 處理接口中的注解方法。
為什么 Mapper 接口沒有實(shí)現(xiàn)類卻能被正常調(diào)用呢栈源?
這是因?yàn)?MyBaits 在 Mapper 接口上使用了動態(tài)代理的一種非常規(guī)的用法挡爵,熟悉這種動態(tài)代
理的用法不僅有利于理解 MyBatis 接口和 XML 的關(guān)系,還能開闊思路 甚垦。
從代理類中可以看到茶鹃,當(dāng)調(diào)用 一個(gè)接口的方法時(shí),會先通過接口的全限定名稱和當(dāng)前調(diào)用
的方法名的組合得到一個(gè)方法 id制轰,這個(gè) id 的值就是映射 XML 中口arnespa ce 和具體方法 id
的組合前计。所以可以在代理方法中使用 sqlSession 以命名空間的方式調(diào)用方法。通過這種方式
可以將接口和 XML 文件中的方法關(guān)聯(lián)起來垃杖。這種代理方式和常規(guī)代理的不同之處在于男杈,這里
沒有對某個(gè)具體類進(jìn)行代理,而是通過代理轉(zhuǎn)化成了對其他代碼的調(diào)用调俘。
由于方法參數(shù)和返回值存在很多種情況伶棒,因此 MyBatis 的內(nèi)部實(shí)現(xiàn)會比上面的邏輯復(fù)雜得
多旺垒,正是因?yàn)?MyBatis 對接口動態(tài)代理的實(shí)現(xiàn),我們在使用接口方式的時(shí)候才會如此容易肤无。如
果大家對 MyBatis 源碼感興趣先蒋,可以通過第 11 章的內(nèi)容了解 MyBatis 的源碼并深入學(xué)習(xí)。
通過本節(jié)這個(gè)簡單的例子宛渐,我們可以了解 MyBatis 動態(tài)代理實(shí)現(xiàn)的方式竞漾,同時(shí)也學(xué)會一種
編程思路:可以通過動態(tài)代理這個(gè)橋梁將對接口方法的調(diào)用轉(zhuǎn)換為對其他方法的調(diào)用 。