1. 程式人生 > 其它 >MyBatis XML對映檔案詳解

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