mapper命名规范_Mybatis系列全解(五):全网最全!详解Mybatis的Mapper映射文件
作者:潘潘
若不是生活所迫,誰(shuí)愿意背負(fù)一身才華。
前言
上節(jié)我們介紹了 《 Mybatis系列全解(四):全網(wǎng)最全!Mybatis配置文件 XML 全貌詳解 》,內(nèi)容很詳細(xì)( 也很枯燥),由于篇幅實(shí)在過(guò)于冗長(zhǎng),我預(yù)計(jì)大家想看完得花上兩段上班地鐵公交車(chē)的時(shí)間 。。。
不過(guò)應(yīng)該有讓大家了解到 Mybatis 的核心配置文件 config.xml 全貌,其中的 元素即是我們本節(jié)準(zhǔn)備登場(chǎng)介紹的 SQL 映射器,上節(jié)有介紹了三種引入 SQL 映射器的方式,本節(jié)我們就主要聊聊它的幾個(gè)頂級(jí)元素用法。
Mybatis 真正強(qiáng)大就在于它的語(yǔ)句映射,這是它的魔力所在,也是基石。由于它異常強(qiáng)大,映射器的 XML 文件就顯得相對(duì)簡(jiǎn)單。如果拿它跟具有相同功能的 JDBC 代碼進(jìn)行對(duì)比,你會(huì)立即發(fā)現(xiàn)省掉了將近 95% 的代碼( 95% 是Mybatis 官網(wǎng)的說(shuō)法 ,我也就引入一下 ),MyBatis 致力于減少使用成本,讓用戶(hù)能更專(zhuān)注于 SQL 代碼。Mybatis系列全解腦圖分享,持續(xù)更新中
目錄
1、mapper 映射器頂級(jí)元素全貌
2、namespace 命名空間
3、select 查詢(xún)
4、insert / update / delete 增刪改
5、cache 緩存
6、cache-ref 緩存引用
7、sql 語(yǔ)句塊
8、parameterMap 參數(shù)映射
9、總結(jié)
mapper 映射器頂級(jí)元素全貌
與其它 ORM 框架如 Hibernate 不同,Mybatis 的框架思想希望開(kāi)發(fā)者能夠直接操作數(shù)據(jù)庫(kù)編寫(xiě) SQL,而不是隱藏起來(lái),讓開(kāi)發(fā)者獨(dú)自面對(duì) Java 對(duì)象,為此 Mybatis 設(shè)計(jì)了 SQL 映射器,任你五招十二式。
映射器有九大頂級(jí)元素 ,基本技能介紹
- select : 用于查詢(xún),支持傳參,返回指定結(jié)果集;
- insert : 用于新增,支持傳參,返回指定結(jié)果集;
- update : 用于更新,支持傳參,返回指定結(jié)果集;
- delete : 用于刪除,支持傳參,返回指定結(jié)果集;
- sql : 被其它語(yǔ)句引用的 可復(fù)用 語(yǔ)句塊;
- cache : 當(dāng)前命名空間緩存配置;
- cache-ref : 引用其它命名空間的緩存配置;
- parameterMap : 參數(shù)映射,已棄用,是它不夠好;
- resultMap : 結(jié)果集映射,它就很好;
九大頂級(jí)元素 ,功能歸類(lèi):
其中頂一元素 parameterMap 已棄用 。
無(wú)論你有多么復(fù)雜的 SQL 操作,最根本的思路都逃不出以上 4 部分。namespace 命名空間
一個(gè)完整的 Mapper 映射文件,需要有約束頭 xml 與 !DOCTYPE ,其次才是 mapper 根元素,最后再是頂級(jí)元素,而其中,namespace 屬性作為 mapper 的唯一標(biāo)識(shí),試回憶:
- 上學(xué)時(shí),6年級(jí)一班23號(hào),能代表唯一的你。
- 編寫(xiě) Java 類(lèi)時(shí),包名 + 類(lèi)名,能代表唯一的類(lèi)。
- 而如今,我們?cè)?Mybatis 中寫(xiě)的每一段 SQL 語(yǔ)句,同樣有唯一的代表方式,那就是「 命名空間標(biāo)識(shí) + 語(yǔ)句id 」,無(wú)論是為了區(qū)分業(yè)務(wù)也好,還是為了拆分服務(wù)也好,反正 Mybatis 讓每一個(gè) mapper.xml 配備一個(gè)唯一命名空間標(biāo)識(shí)。
每一段 SQL 語(yǔ)句都是唯一定義的,我們?cè)?Mybatis 中用「 命名空間標(biāo)識(shí) + 語(yǔ)句塊 ID 」作為唯一的標(biāo)識(shí),組合之后在 Mybatis 二級(jí)緩存中可以作為本地 map 集合 緩存 的唯一Key ,也可以用于 Dao 接口的 映射 綁定,還能作為唯一 代理 標(biāo)識(shí)。總之,我們希望避免命名沖突和重復(fù)定義,所以,擁有這么一個(gè)唯一標(biāo)識(shí) ,它就至少有一億個(gè)利好。
select 查詢(xún)
select 查詢(xún)語(yǔ)句,幾乎是我們最高頻的使用元素,所以 Mybatis 在這塊沒(méi)少下功夫,目的就是通過(guò)提供盡可能多的便利,讓我們的查詢(xún)操作變得簡(jiǎn)單。 一個(gè)查詢(xún)用戶(hù) User 的查詢(xún)語(yǔ)句可以這么編寫(xiě):
<select id="selectUser" parameterType="int" resultType="hashmap">select * from t_user where id = #{id} </select>- id屬性:在當(dāng)前 mapper.xml 命名空間下,它的 id 值是唯一的( 不過(guò)如果在不同的 mapper.xml 命名空間下,則允許有相同的的 id 值 )
- parameterType 屬性:代表傳入的參數(shù)類(lèi)型,這里是 int (或 Integer)類(lèi)型
- resultType屬性:代表返回結(jié)果類(lèi)型,這里指定返回一個(gè) hashMap 類(lèi)型的對(duì)象,mybatis 會(huì)把查詢(xún)出來(lái)的數(shù)據(jù)表記錄對(duì)應(yīng)的 ' 字段列名 - 字段值 ',自動(dòng)映射為 map 集合的 key - value 。
注意參數(shù)符號(hào):
#{id}#{} 告訴 MyBatis 創(chuàng)建一個(gè)預(yù)編譯語(yǔ)句(PreparedStatement)參數(shù),在 JDBC 中,這樣的一個(gè)參數(shù)在 SQL 中會(huì)由一個(gè) “ ? ” 來(lái)標(biāo)識(shí),并被傳遞到一個(gè)新的預(yù)編譯語(yǔ)句中,就像這樣:
// 近似的 JDBC 代碼,非 MyBatis 代碼... String selectUser = " select * from t_user where id = ? "; PreparedStatement ps = conn.prepareStatement(selectUser); ps.setInt(1,id);#{} 作為占位符,${} 作為替換符,兩者沒(méi)有孰輕孰重,只不過(guò)應(yīng)用場(chǎng)景不同,適當(dāng)取舍即可。
我們希望完成類(lèi)似 JDBC 中的 PrepareStatement 預(yù)編譯處理 ,可以使用 #{} ,它會(huì)在替換占位符時(shí)首尾添加上單引號(hào) '' ,能有效防止 SQL 注入 風(fēng)險(xiǎn)。
例如使用 ${} 操作刪除 ( 就很有問(wèn)題!)
// 1、使用 ${} 有注入風(fēng)險(xiǎn) delete from t_user where id = ${id}// 2、正常傳值,id 傳入 1 delete from t_user where id = 1 // 結(jié)果刪除了id=1 的記錄// 3、注入風(fēng)險(xiǎn),id 傳入 1 or 1=1 delete from t_user where id = 1 or 1=1 // 全表刪除了再看看 #{} 是如何規(guī)避 SQL 注入 的:
// 1、使用 #{} 有效防止注入風(fēng)險(xiǎn) delete from t_user where id = #{id}// 2、正常傳值,id 傳入 1 delete from t_user where id = '1' // 結(jié)果刪除了id=1 的記錄// 3、注入風(fēng)險(xiǎn),id 傳入 1 or 1=1 delete from t_user where id = '1 or 1=1' // SQL 語(yǔ)句報(bào)錯(cuò),表數(shù)據(jù)安全雖然在防止 SQL 注入方面,${} 確實(shí)無(wú)能為力,不過(guò)我們 ${} 在其它方面可不容小覷,例如它允許你靈活地進(jìn)行 動(dòng)態(tài)表和動(dòng)態(tài)列名的替換 操作,例如:
// 1、靈活查詢(xún)指定表數(shù)據(jù) select * from ${tableName} // 傳入 tableName參數(shù) = t_user , 結(jié)果 select * from t_user // 2、靈活查詢(xún)不同列條件數(shù)據(jù) select * from t_user where ${colunmName} = ${value}// 傳入 colunmName參數(shù) = name , value參數(shù) = '潘潘', 結(jié)果 select * from t_user where name = '潘潘'// 傳入 colunmName參數(shù) = id , value參數(shù) = 1, 結(jié)果 select * from t_user where id = 1以上的 ${} 替換列名與表名的方式非常靈活,不過(guò)確實(shí)存在 SQL 注入風(fēng)險(xiǎn),所以在考慮使用 #{} 或 ${} 前,需要評(píng)估風(fēng)險(xiǎn),避免風(fēng)險(xiǎn),允許的情況下,我建議使用 #{} 。當(dāng)然,select 元素允許你配置很多屬性來(lái)配置每條語(yǔ)句的行為細(xì)節(jié)。
<select id="selectUser" parameterType="int"parameterMap="deprecated"resultType="hashmap"resultMap="personResultMap"flushCache="false"useCache="true"timeout="10"fetchSize="256"statementType="PREPARED"resultSetType="FORWARD_ONLY"databaseId="mysql"resultOrdered="false"resultSets="rs1,rs2,rs3">select * from t_user </select>下面詳細(xì)介紹一下,略微冗長(zhǎng),一口氣干完吧:
- id 必填項(xiàng),在命名空間下的唯一標(biāo)識(shí),可被 Mybatis 引用,如果存在相同的 “ 命名空間 + 語(yǔ)句id ” 組合,Mybatis 將拋出異常;
- parameterType 可選項(xiàng),傳入語(yǔ)句的參數(shù)的類(lèi)全限定名或別名,可以是基本類(lèi)型、map 或 JavaBean 等復(fù)雜的參數(shù)類(lèi)型傳遞給 SQL;
- parameterMap 用于引用外部 parameterMap 的屬性塊,目前已被廢棄。以后請(qǐng)使用行內(nèi)參數(shù)映射和 parameterType 屬性。
- resultType 可選項(xiàng),定義類(lèi)的全路徑,在允許自動(dòng)匹配的情況下,結(jié)果集將通過(guò) Javaben 的規(guī)范映射,或定義為 int 、double、float 等參數(shù);也可以使用別名,但是要符合別名規(guī)范和定義。 resultType 和 resultMap 之間只能同時(shí)使用一個(gè)。(日常中,比如我們統(tǒng)計(jì)結(jié)果總條數(shù)的時(shí)候可以設(shè)置為 int );
- resultMap 可選項(xiàng),對(duì)外部 resultMap 的命名引用。結(jié)果映射是 MyBatis 最強(qiáng)大的特性,如果你對(duì)其理解透徹,許多復(fù)雜的映射問(wèn)題都能迎刃而解,后面一對(duì)一、一對(duì)多、多對(duì)多我們會(huì)有一篇文章單獨(dú)講解。 resultType 和 resultMap 之間只能同時(shí)使用一個(gè)。
- flushCache 可選項(xiàng),清空緩存,將其設(shè)置為 true 后,只要語(yǔ)句被調(diào)用,都會(huì)導(dǎo)致本地緩存和二級(jí)緩存被清空,默認(rèn)值:false。
- useCache 可選項(xiàng),使用緩存,將其設(shè)置為 true 后,將會(huì)導(dǎo)致本條語(yǔ)句的結(jié)果被二級(jí)緩存緩存起來(lái),默認(rèn)值:對(duì) select 元素為 true。
- timeout 可選項(xiàng),這個(gè)設(shè)置是在拋出異常之前,驅(qū)動(dòng)程序等待數(shù)據(jù)庫(kù)返回請(qǐng)求結(jié)果的秒數(shù)。默認(rèn)值為未設(shè)置(unset)(依賴(lài)數(shù)據(jù)庫(kù)驅(qū)動(dòng))。
- fetchSize 可選項(xiàng),獲取記錄的總條數(shù)設(shè)定。這是一個(gè)給驅(qū)動(dòng)的建議值,嘗試讓驅(qū)動(dòng)程序每次批量返回的結(jié)果行數(shù)等于這個(gè)設(shè)置值。 默認(rèn)值為未設(shè)置(unset)(依賴(lài)驅(qū)動(dòng))。由于性能問(wèn)題,建議在 sql 做分頁(yè)處理。
- statementType 可選項(xiàng),可選 STATEMENT,PREPARED 或 CALLABLE。這會(huì)讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,默認(rèn)值:PREPARED。
- resultSetType 可選項(xiàng),FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等價(jià)于 unset) 中的一個(gè),默認(rèn)值為 unset (依賴(lài)數(shù)據(jù)庫(kù)驅(qū)動(dòng))。
- FORWARD_ONLY,只允許游標(biāo)向前訪問(wèn);
- SCROLL_SENSITIVE,允許游標(biāo)雙向滾動(dòng),但不會(huì)及時(shí)更新數(shù)據(jù),也就是說(shuō)如果數(shù)據(jù)庫(kù)中的數(shù)據(jù)被修改過(guò),并不會(huì)在resultSet中及時(shí)更新出來(lái);
- SCROLL_INSENSITIVE ,允許游標(biāo)雙向滾動(dòng),如果數(shù)據(jù)庫(kù)中的數(shù)據(jù)被修改過(guò),會(huì)及時(shí)更新到resultSet;
- databaseId 可選項(xiàng),如果配置了數(shù)據(jù)庫(kù)廠商標(biāo)識(shí)(databaseIdProvider),MyBatis 會(huì)加載所有不帶 databaseId 或匹配當(dāng)前 databaseId 的語(yǔ)句;如果帶和不帶的語(yǔ)句都有,則不帶的會(huì)被忽略。
- resultOrdered 可選項(xiàng),這個(gè)設(shè)置僅針對(duì)嵌套結(jié)果 select 語(yǔ)句:如果為 true,將會(huì)假設(shè)包含了嵌套結(jié)果集或是分組,當(dāng)返回一個(gè)主結(jié)果行時(shí),就不會(huì)產(chǎn)生對(duì)前面結(jié)果集的引用。 這就使得在獲取嵌套結(jié)果集的時(shí)候不至于內(nèi)存不夠用。默認(rèn)值:false。
- resultSets 這個(gè)設(shè)置僅適用于多結(jié)果集的情況。它將列出語(yǔ)句執(zhí)行后返回的結(jié)果集并賦予每個(gè)結(jié)果集一個(gè)名稱(chēng),多個(gè)名稱(chēng)之間以逗號(hào)分隔。
insert / update / delete 增刪改
數(shù)據(jù)變更語(yǔ)句 insert,update 和 delete 的實(shí)現(xiàn)非常接近,而且相對(duì)于 select 元素而言要簡(jiǎn)單許多。
<insertid="insertUser"parameterType="domain.vo.User"flushCache="true"statementType="PREPARED"keyProperty=""keyColumn=""useGeneratedKeys=""timeout="20"><updateid="updateUser"parameterType="domain.vo.User"flushCache="true"statementType="PREPARED"timeout="20"><deleteid="deleteUser"parameterType="domain.vo.User"flushCache="true"statementType="PREPARED"timeout="20">其中大部分屬性和 select 元素相同,我們介紹 3 個(gè)不同的屬性:
- useGeneratedKeys : (僅適用于 insert 和 update)這會(huì)令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來(lái)取出由數(shù)據(jù)庫(kù)內(nèi)部生成的主鍵(比如:像 MySQL 和 SQL Server 這樣的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)的自動(dòng)遞增字段),默認(rèn)值:false。
- keyProperty : (僅適用于 insert 和 update)指定能夠唯一識(shí)別對(duì)象的屬性,MyBatis 會(huì)使用 getGeneratedKeys 的返回值或 insert 語(yǔ)句的 selectKey 子元素設(shè)置它的值,默認(rèn)值:未設(shè)置(unset)。如果生成列不止一個(gè),可以用逗號(hào)分隔多個(gè)屬性名稱(chēng)。
- keyColumn : (僅適用于 insert 和 update)設(shè)置生成鍵值在表中的列名,在某些數(shù)據(jù)庫(kù)(像 PostgreSQL)中,當(dāng)主鍵列不是表中的第一列的時(shí)候,是必須設(shè)置的。如果生成列不止一個(gè),可以用逗號(hào)分隔多個(gè)屬性名稱(chēng)。
我們先看看 insert,update 和 delete 語(yǔ)句的示例:
<insert id="insertUser">insert into t_user (id,name) values (#{id},#{name}) </insert><update id="updateUser">update t_user set name = #{name} where id = #{id} </update><delete id="deleteUser">delete from t_user where id = #{id} </delete>如前所述,插入語(yǔ)句的配置規(guī)則更加豐富,在插入語(yǔ)句里面有一些額外的屬性和子元素用來(lái)處理主鍵的生成,并且提供了多種生成方式。
首先,如果你的數(shù)據(jù)庫(kù)支持 自動(dòng)生成主鍵 的字段(比如 MySQL 和 SQL Server),那么你可以設(shè)置 useGeneratedKeys=”true”,然后再把 keyProperty 設(shè)置為目標(biāo)屬性就 OK 了。例如,如果上面的 t_user 表已經(jīng)在 id 列上使用了自動(dòng)生成,那么語(yǔ)句可以修改為:
<insert id="insertUser" useGeneratedKeys="true"keyProperty="id">insert into t_user (name) values (#{name}) </insert>如果你的數(shù)據(jù)庫(kù)還支持多行插入, 你也可以傳入一個(gè) User 數(shù)組或集合,并返回自動(dòng)生成的主鍵。
<insert id="insertUser" useGeneratedKeys="true"keyProperty="id">insert into t_user (name) values <foreach item="item" collection="list" separator=",">(#{item.name})</foreach> </insert>對(duì)于不支持自動(dòng)生成主鍵列的數(shù)據(jù)庫(kù)和可能不支持自動(dòng)生成主鍵的 JDBC 驅(qū)動(dòng),MyBatis 有另外一種方法來(lái)生成主鍵。
這里有一個(gè)簡(jiǎn)單(也很傻)的示例,它可以生成一個(gè)隨機(jī) ID(不建議實(shí)際使用,這里只是為了展示 MyBatis 處理問(wèn)題的靈活性和寬容度):
<insert id="insertUser"><selectKey keyProperty="id" resultType="int" order="BEFORE">select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1</selectKey>insert into t_user (id, name)values (#{id}, #{name}) </insert>在上面的示例中,首先會(huì)運(yùn)行 selectKey 元素中的語(yǔ)句,并設(shè)置 User 的 id,然后才會(huì)調(diào)用插入語(yǔ)句。這樣就實(shí)現(xiàn)了數(shù)據(jù)庫(kù)自動(dòng)生成主鍵類(lèi)似的行為,同時(shí)保持了 Java 代碼的簡(jiǎn)潔。
selectKey 元素描述如下:
<selectKeykeyProperty="id"resultType="int"order="BEFORE"statementType="PREPARED">selectKey 中的 order 屬性有2個(gè)選擇:BEFORE 和 AFTER 。
- BEFORE:表示先執(zhí)行selectKey的語(yǔ)句,然后將查詢(xún)到的值設(shè)置到 JavaBean 對(duì)應(yīng)屬性上,然后再執(zhí)行 insert 語(yǔ)句。
- AFTER:表示先執(zhí)行 AFTER 語(yǔ)句,然后再執(zhí)行 selectKey 語(yǔ)句,并將 selectKey 得到的值設(shè)置到 JavaBean 中的屬性。上面示例中如果改成 AFTER,那么插入的 id 就會(huì)是空值,但是返回的 JavaBean 屬性?xún)?nèi)會(huì)有值。
cache 緩存
緩存對(duì)于互聯(lián)網(wǎng)系統(tǒng)來(lái)說(shuō)特別常見(jiàn),其特點(diǎn)就是將數(shù)據(jù)保存在內(nèi)存中。MyBatis 內(nèi)置了一個(gè)強(qiáng)大的事務(wù)性查詢(xún)緩存機(jī)制,它可以非常方便地配置和定制。 為了使它更加強(qiáng)大而且易于配置,我們對(duì) MyBatis 3 中的緩存實(shí)現(xiàn)進(jìn)行了許多改進(jìn)。
默認(rèn)情況下,只啟用了本地的會(huì)話緩存(即一級(jí)緩存,sqlSession級(jí)別 ),它僅僅對(duì)一個(gè)會(huì)話中的數(shù)據(jù)進(jìn)行緩存。 要啟用全局的二級(jí)緩存,首先在全局配置文件config.xml文件中加入如下代碼:
<!--開(kāi)啟二級(jí)緩存--> <settings> <setting name="cacheEnabled" value="true"/> </settings>其次在UserMapper.xml文件中開(kāi)啟緩存:
<!--開(kāi)啟二級(jí)緩存--> <cache></cache>基本上就是這樣。這個(gè)簡(jiǎn)單語(yǔ)句的效果如下:
- 映射語(yǔ)句文件中的所有 select 語(yǔ)句的結(jié)果將會(huì)被緩存。
- 映射語(yǔ)句文件中的所有 insert、update 和 delete 語(yǔ)句會(huì)刷新緩存。
- 緩存會(huì)使用最近最少使用算法(LRU, Least Recently Used)算法來(lái)清除不需要的緩存。
- 緩存不會(huì)定時(shí)進(jìn)行刷新(也就是說(shuō),沒(méi)有刷新間隔)。
- 緩存會(huì)保存列表或?qū)ο?#xff08;無(wú)論查詢(xún)方法返回哪種)的 1024 個(gè)引用。
- 緩存會(huì)被視為讀/寫(xiě)緩存,這意味著獲取到的對(duì)象并不是共享的,可以安全地被調(diào)用者修改,而不干擾其他調(diào)用者或線程所做的潛在修改。
這些屬性可以通過(guò) cache 元素的屬性來(lái)修改。比如:
<cacheeviction="FIFO"flushInterval="60000"size="512"readOnly="true"/>上面表示了一套更高級(jí)的緩存配置,首先創(chuàng)建了一個(gè) FIFO 緩存,每隔 60 秒刷新,最多可以存儲(chǔ)結(jié)果對(duì)象或列表的 512 個(gè)引用,然后返回的對(duì)象被設(shè)置成只讀的,因此對(duì)它們進(jìn)行修改可能會(huì)在不同線程中的調(diào)用者產(chǎn)生沖突。
緩存可用的清除策略有:
- LRU – 最近最少使用:移除最長(zhǎng)時(shí)間不被使用的對(duì)象。
- FIFO – 先進(jìn)先出:按對(duì)象進(jìn)入緩存的順序來(lái)移除它們。
- SOFT – 軟引用:基于垃圾回收器狀態(tài)和軟引用規(guī)則移除對(duì)象。
- WEAK – 弱引用:更積極地基于垃圾收集器狀態(tài)和弱引用規(guī)則移除對(duì)象。
flushInterval(刷新間隔)屬性可以被設(shè)置為任意的正整數(shù),設(shè)置的值應(yīng)該是一個(gè)以毫秒為單位的合理時(shí)間量。 默認(rèn)情況是不設(shè)置,也就是沒(méi)有刷新間隔,緩存僅僅會(huì)在調(diào)用語(yǔ)句時(shí)刷新。
size(引用數(shù)目)屬性可以被設(shè)置為任意正整數(shù),要注意欲緩存對(duì)象的大小和運(yùn)行環(huán)境中可用的內(nèi)存資源。默認(rèn)值是 1024。
readOnly(只讀)屬性可以被設(shè)置為 true 或 false。只讀的緩存會(huì)給所有調(diào)用者返回緩存對(duì)象的相同實(shí)例。 因此這些對(duì)象不能被修改。這就提供了可觀的性能提升。而可讀寫(xiě)的緩存會(huì)(通過(guò)序列化)返回緩存對(duì)象的拷貝。 速度上會(huì)慢一些,但是更安全,因此默認(rèn)值是 false。
二級(jí)緩存是事務(wù)性的。這意味著,當(dāng) SqlSession 完成并提交 ( commit ) 時(shí),或是完成并回滾 ( close ) 時(shí),二級(jí)緩存都會(huì)被刷新。不管是否配置了 flushCache=true 。Mybatis 的緩存包括一級(jí)緩存(sqlSession 級(jí)別)和二級(jí)緩存(mapper 級(jí)別),所以 mapper 映射器中配置的是二級(jí)緩存,我們先大概知道有這個(gè)概念,因?yàn)楹罄m(xù)我們會(huì)針對(duì)這兩種緩存進(jìn)行詳細(xì)介紹,而且還會(huì)講解如何自定義緩存,因?yàn)?Mybatis 的緩存默認(rèn)都是以 map 的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)在本地,所以自定義緩存可以把存儲(chǔ)介質(zhì)拓展到磁盤(pán)或數(shù)據(jù)庫(kù)redis等;而且一級(jí)緩存是默認(rèn)開(kāi)啟的,二級(jí)緩存需要我們手工開(kāi)啟,這些后續(xù)都會(huì)詳細(xì)講解,提前預(yù)告。
緩存獲取順序:二級(jí)緩存 > 一級(jí)緩存 > 數(shù)據(jù)庫(kù)cache-ref 引用緩存
回想一下 cache 的內(nèi)容,對(duì)某一命名空間的語(yǔ)句,只會(huì)使用該命名空間的緩存進(jìn)行緩存或刷新。 但你可能會(huì)想要在多個(gè)命名空間中共享相同的緩存配置和實(shí)例。要實(shí)現(xiàn)這種需求,你可以使用 cache-ref 元素來(lái)引用另一個(gè)緩存。
<cache-ref namespace="com.vo.UserMapper"/>sql 語(yǔ)句塊
這個(gè)元素可以用來(lái)定義可重用的 SQL 代碼片段,以便在其它語(yǔ)句中使用。 參數(shù)可以靜態(tài)地(在加載的時(shí)候)確定下來(lái),并且可以在不同的 include 元素中定義不同的參數(shù)值。比如:
<sql id="userColumns"> ${alias}.id,${alias}.name </sql>這個(gè) SQL 片段可以在其它語(yǔ)句中使用,例如:
<select id="selectUsers" resultType="map">select<include refid="userColumns"><property name="alias" value="t1"/></include>,<include refid="userColumns"><property name="alias" value="t2"/></include>from t_user t1 cross join t_user t2 </select>也可以在 include 元素的 refid 屬性或多層內(nèi)部語(yǔ)句中使用屬性值,例如:
<sql id="sql1">${prefix}_user </sql><sql id="sql2">from<include refid="${include_target}"/> </sql><select id="select" resultType="map">selectid, name<include refid="sql2"><property name="prefix" value="t"/><property name="include_target" value="sql1"/></include> </select>parameterMap 參數(shù)映射
parameterMap 元素官方已經(jīng)不建議使用,并且再后續(xù)版本會(huì)退出舞臺(tái)。首先對(duì)于我們 Java 來(lái)說(shuō),特別不希望在代碼中通過(guò)傳遞 map 來(lái)傳參,這樣對(duì)于后續(xù)維護(hù)或者參數(shù)查找都是極不負(fù)責(zé)任的,我們推薦使用 JavaBean 來(lái)傳值參數(shù),這是 parameterMap 被拋棄的其中一個(gè)原因;另外也由于 parameterType 屬性的誕生就能很好的代替 parameterMap ,并且還能自定義 JavaBean 類(lèi)型的傳參,所以 parameterMap 退出舞臺(tái),實(shí)屬正常。
總結(jié)
我一直來(lái)都希望自己只輸出觀點(diǎn),而不是輸出字典,但其中有些知識(shí)點(diǎn)又是極其冗雜,知識(shí)輸出真是個(gè)難搞的差事,如何既能把知識(shí)脈絡(luò)梳理的完整,又能講得淺顯易懂,言簡(jiǎn)意賅,確實(shí)是后續(xù)文章分解輸出的研究方向。
本篇完,本系列下一篇我們講《 Mybatis系列全解(六):Mybatis最硬核的API你知道幾個(gè)? 》。BIU ~ 文章持續(xù)更新,微信搜索「潘潘和他的朋友們」第一時(shí)間閱讀,隨時(shí)有驚喜。本文會(huì)在 GitHub https://github.com/JavaWord 收錄,熱騰騰的技術(shù)、框架、面經(jīng)、解決方案,我們都會(huì)以最美的姿勢(shì)第一時(shí)間送達(dá),歡迎 Star ~ 我們未來(lái) 不止文章!想進(jìn)讀者群的伙伴歡迎撩我個(gè)人號(hào):panshenlian,備注「加群」我們?nèi)豪餁g聊吧 ~總結(jié)
以上是生活随笔為你收集整理的mapper命名规范_Mybatis系列全解(五):全网最全!详解Mybatis的Mapper映射文件的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 如何清洗海尔空调自动清洁功能?
- 下一篇: h2 不能访问localhost_Spr