MyBatis XML對映檔案詳解
MyBatis 的真正強大在於它的對映語句,也是它的魔力所在。由於它的異常強大,對映器的 XML 檔案就顯得相對簡單。在MyBatis開發中,涉及到主要開發要素是:Dao介面類,Mapper對映檔案,以及PO類。它們之間的關係如下:
對映器(mapper)的XML檔案,有幾個頂級元素:
- select – 對映查詢語句
- insert – 對映插入語句
- update – 對映更新語句
- delete – 對映刪除語句
- sql – 可被其他語句引用的可重用語句塊。
- cache – 給定名稱空間的快取配置。
- cache-ref – 其他名稱空間快取配置的引用。
- resultMap – 是最複雜也是最強大的元素,用來描述如何從資料庫結果集中來載入物件。
一、select元素
1. 最基本的查詢
<select id="getUserById" resultType="MemberUser" parameterType="int"> select ID,NAME,PERSONMOBILE,ADDRESS,AGE FROM MEMBER_USER WHERE ID = #{id} </select>
上述配置類似於:
// Similar JDBC code, NOT MyBatis… String selectMember = "select ID,NAME,PERSONMOBILE,ADDRESS,AGE FROM MEMBER_USER WHERE ID=?"; PreparedStatement ps= conn.prepareStatement(selectMember); ps.setInt(1,id);
2. select 元素有很多屬性允許你配置,來決定每條語句的作用細節
示範:
<select id="selectPerson" parameterType="int" parameterMap="deprecated" resultType="hashmap" resultMap="personResultMap" flushCache="false" useCache="true" timeout="10000" fetchSize="256" statementType="PREPARED" resultSetType="FORWARD_ONLY">
詳細說明:
屬性 | 描述 |
---|---|
id | 在名稱空間中唯一的識別符號,可以被用來引用這條語句。 |
parameterType | 將會傳入這條語句的引數類的完全限定名或別名。這個屬性是可選的,因為 MyBatis 可以通過 TypeHandler 推斷出具體傳入語句的引數,預設值為 unset。 |
resultType | 從這條語句中返回的期望型別的類的完全限定名或別名。注意如果是集合情形,那應該是集合可以包含的型別,而不能是集合本身。使用 resultType 或 resultMap,但不能同時使用。 |
resultMap | 外部 resultMap 的命名引用。結果集的對映是 MyBatis 最強大的特性,對其有一個很好的理解的話,許多複雜對映的情形都能迎刃而解。使用 resultMap 或 resultType,但不能同時使用。 |
flushCache | 將其設定為 true,任何時候只要語句被呼叫,都會導致本地快取和二級快取都會被清空,預設值:false。 |
useCache | 將其設定為 true,將會導致本條語句的結果被二級快取,預設值:對 select 元素為 true。 |
timeout | 這個設定是在丟擲異常之前,驅動程式等待資料庫返回請求結果的秒數。預設值為 unset(依賴驅動)。 |
fetchSize | 這是嘗試影響驅動程式每次批量返回的結果行數和這個設定值相等。預設值為 unset(依賴驅動)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,預設值:PREPARED。 |
resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一個,預設值為 unset (依賴驅動)。 |
databaseId | 如果配置了 databaseIdProvider,MyBatis 會載入所有的不帶 databaseId 或匹配當前 databaseId 的語句;如果帶或者不帶的語句都有,則不帶的會被忽略。 |
resultOrdered | 這個設定僅針對巢狀結果 select 語句適用:如果為 true,就是假設包含了巢狀結果集或是分組了,這樣的話當返回一個主結果行的時候,就不會發生有對前面結果集的引用的情況。這就使得在獲取巢狀的結果集的時候不至於導致記憶體不夠用。預設值:false。 |
resultSets | 這個設定僅對多結果集的情況適用,它將列出語句執行後返回的結果集並每個結果集給一個名稱,名稱是逗號分隔的。 |
二、insert、update、delete元素
1. 資料變更語句 insert,update 和 delete 的實現非常接近,參考如下配置:
<!--Oracle的實現自增長主鍵的方式--> <insert id="insertUser" parameterType="MemberUser"> <selectKey keyProperty="id" resultType="int" order="BEFORE"> select SEQ_MEMBER_USER.nextval from DUAL </selectKey> INSERT INTO MEMBER_USER (ID, NAME, PERSONMOBILE, ADDRESS, AGE) VALUES(#{id}, #{name}, #{personMobile}, #{address}, #{age}) </insert> <update id="updateUser" parameterType="MemberUser"> update MEMBER_USER set NAME = #{name}, PERSONMOBILE = #{personMobile}, ADDRESS = #{address}, AGE = #{age} where id = #{id} </update> <delete id="deleteUser" parameterType="int"> delete from MEMBER_USER where ID = #{id} </delete>
2 .Insert, Update 和 Delete 的屬性:
屬性 | 描述 |
---|---|
id | 名稱空間中的唯一識別符號,可被用來代表這條語句。 |
parameterType | 將要傳入語句的引數的完全限定類名或別名。這個屬性是可選的,因為 MyBatis 可以通過 TypeHandler 推斷出具體傳入語句的引數,預設值為 unset。 |
flushCache | 將其設定為 true,任何時候只要語句被呼叫,都會導致本地快取和二級快取都會被清空,預設值:true(對應插入、更新和刪除語句)。 |
timeout | 這個設定是在丟擲異常之前,驅動程式等待資料庫返回請求結果的秒數。預設值為 unset(依賴驅動)。 |
statementType | STATEMENT,PREPARED 或 CALLABLE 的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,預設值:PREPARED。 |
useGeneratedKeys | (僅對 insert 和 update 有用)這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由資料庫內部生成的主鍵(比如:像 MySQL 和 SQL Server 這樣的關係資料庫管理系統的自動遞增欄位),預設值:false。 |
keyProperty | (僅對 insert 和 update 有用)唯一標記一個屬性,MyBatis 會通過 getGeneratedKeys 的返回值或者通過 insert 語句的 selectKey 子元素設定它的鍵值,預設:unset。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 |
keyColumn | (僅對 insert 和 update 有用)通過生成的鍵值設定表中的列名,這個設定僅在某些資料庫(像 PostgreSQL)是必須的,當主鍵列不是表中的第一列的時候需要設定。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 |
databaseId | 如果配置了 databaseIdProvider,MyBatis 會載入所有的不帶 databaseId 或匹配當前 databaseId 的語句;如果帶或者不帶的語句都有,則不帶的會被忽略。 |
3. 關於insert元素
如果你的資料庫支援自動生成主鍵的欄位(比如 MySQL 和 SQL Server),那麼你可以設定 useGeneratedKeys=”true”,然後再把 keyProperty 設定到目標屬性上就OK了。示範:
<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id"> insert into Author (username,password,email,bio) values (#{username},#{password},#{email},#{bio}) </insert>
如果是Oracle資料庫,則用上面示範程式碼即可。selectKey 元素描述如下:
<selectKey keyProperty="id" resultType="int" order="BEFORE" statementType="PREPARED">
selectKey 的屬性:
屬性 | 描述 |
---|---|
keyProperty | selectKey 語句結果應該被設定的目標屬性。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 |
keyColumn | 匹配屬性的返回結果集中的列名稱。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 |
resultType | 結果的型別。MyBatis 通常可以推算出來,但是為了更加確定寫上也不會有什麼問題。MyBatis 允許任何簡單型別用作主鍵的型別,包括字串。如果希望作用於多個生成的列,則可以使用一個包含期望屬性的 Object 或一個 Map。 |
order | 這可以被設定為 BEFORE 或 AFTER。如果設定為 BEFORE,那麼它會首先選擇主鍵,設定 keyProperty 然後執行插入語句。如果設定為 AFTER,那麼先執行插入語句,然後是 selectKey 元素 - 這和像 Oracle 的資料庫相似,在插入語句內部可能有嵌入索引呼叫。 |
statementType | 與前面相同,MyBatis 支援 STATEMENT,PREPARED 和 CALLABLE 語句的對映型別,分別代表 PreparedStatement 和 CallableStatement 型別。 |
三、sql元素
這個元素可以被用來定義可重用的 SQL 程式碼段,可以包含在其他語句中。
1. 簡單示範:
<!-- 用來定義可重用的SQL程式碼段 --> <sql id="selectProdSQL"> PRODID,PRODSERIAL,PRODNAME,CATEGORYNAME,PRODSPEC,PRODPRICE,PRODDESC,PRODIMAGE,ISNEW,ISRECOMMEND,ISSHOW,USERNAME,HANDLETIME,PRODTHUMBNAIL </sql> <!--以單個物件方式返回--> <select id="getProductById" resultType="Product" parameterType="int"> select <include refid="selectProdSQL"/> FROM PRODUCT WHERE PRODID = #{prodId} </select>
2. 進階用法:
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
這個 SQL 片段可以被包含在其他語句中,例如:
<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 some_table t1 cross join some_table t2 </select>
四、resultMap元素
ResultMap 的設計就是簡單語句不需要明確的結果對映,而很多複雜語句確實需要描述它們 的關係。resultmap構成元素:
<!--column不做限制,可以為任意表的欄位,而property須為type 定義的pojo屬性--> <resultMap id="唯一的標識" type="對映的pojo物件"> <id column="表的主鍵欄位,或者可以為查詢語句中的別名欄位" jdbcType="欄位型別" property="對映pojo物件的主鍵屬性" /> <result column="表的一個欄位(可以為任意表的一個欄位)" jdbcType="欄位型別" property="對映到pojo物件的一個屬性(須為type定義的pojo物件中的一個屬性)"/> <association property="pojo的一個物件屬性" javaType="pojo關聯的pojo物件"> <id column="關聯pojo物件對應表的主鍵欄位" jdbcType="欄位型別" property="關聯pojo物件的主席屬性"/> <result column="任意表的欄位" jdbcType="欄位型別" property="關聯pojo物件的屬性"/> </association> <!-- 集合中的property須為oftype定義的pojo物件的屬性--> <collection property="pojo的集合屬性" ofType="集合中的pojo物件"> <id column="集合中pojo物件對應的表的主鍵欄位" jdbcType="欄位型別" property="集合中pojo物件的主鍵屬性" /> <result column="可以為任意表的欄位" jdbcType="欄位型別" property="集合中的pojo物件的屬性" /> </collection> </resultMap>
正常情況,它用來作為將資料庫欄位與PO類的欄位進行對映,比如:
<resultMap id="BaseResultMap" type="com.meikai.shop.entity.TShopSku"> <id column="ID" jdbcType="BIGINT" property="id" /> <result column="SKU_NAME" jdbcType="VARCHAR" property="skuName" /> <result column="CATEGORY_ID" jdbcType="BIGINT" property="categoryId" /> </resultMap>
本文參考:
https://www.cnblogs.com/wolf-lifeng/p/11153569.html
https://www.w3cschool.cn/mybatis/f4uw1ilx.html
https://www.cnblogs.com/kenhome/p/7764398.html