XML對映器


SQL對映檔案的幾個頂級元素:

  • cache - 該名稱空間的快取配置

  • cache-ref - 引用其他名稱空間的快取配置

  • resultMap - 描述如何從資料庫結果集中載入物件

  • sql - 可被其他語句引用的可重用語句塊

  • insert - 增

  • update - 改

  • delete - 刪

  • select - 查

select屬性

屬性 描述
id 識別符號,與Mapper中對應方法的方法名一致
parameterType 傳入這條語句的引數的類全限定名或別名
resultType 返回結果的類全限定名或別名,如果返回的是集合,應設定為集合包含的型別而不是集合本身的型別。resultType和resultMap之間只能使用一個
resultMap 對外部resultMap的命名引用,結果對映是Mybatis的最強大的特性

sql

sql元素可以用來定義可重用的SQL程式碼片段,以便在其他語句中使用。引數可以靜態地(載入的時候)確定下來並且可以在不同的include元素中定義不同的引數值

<sql id="userColumns">
${alias}.id,${alias}.usernname,${alias}.password
</sql>

常用在include元素的refid屬性或內部語句中使用屬性值

<sql id="sometable">
${preifx}Table
</sql> <sql id="someinclude">
FROM
<include refid="${include_target}"/>
</sql> <select id="select" resultType="Map">
SELECT
field1,field2,field3
<include refid="someinclude">
<property name="prefix" value="Some"/>
<property name="include_target" value="sometable"/>
</include>
</select>

ResultMap

一對一查詢:

<!-- 屬性名不一致或進行關聯查詢時,可用resultMap標籤
以查詢訂單為例,從查詢訂單角度出發為一對一,因為一個訂單隻會是一個人下的 -->
1)改造實體類:
<!-- 在訂單類中新增User屬性,即一個引用型別 --> 2)編寫resultMap:
<resultMap type="order" id="orderUserResultMap">
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
...
<result property="note" column="note"/>
<association property="user" javaType="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
...
</association>
</resultMap> 3)呼叫例項:
<!-- 一對一關聯,查詢訂單,訂單內部包含使用者屬性 -->
<select id="queryOrderUserResultMap" resultMap="orderUserResultMap">
SELECT
o.id,
o.user_id,
o.number,
o.createtime,
o.note,
u.username,
u.address
FROM
`order` o
LEFT JOIN `user` u ON o.user_id = u.id
</select>

一對多查詢:

<!-- 查詢所有使用者資訊及相關訂單 -->
<!-- 對於使用者而言,一個使用者可能對應多個不同的訂單,即一對多 -->
1)改造實體類:
新增訂單集合屬性,如:List< Order > orders 2)編寫resultMap:
<resultMap type="user" id="userOrderResultMap">
<id property="id" column="id" />
<result property="username" column="username" />
<result property="birthday" column="birthday" />
<result property="sex" column="sex" />
<result property="address" column="address" /> <!-- 配置一對多的關係
property:填寫pojo類中List集合類類屬性的名稱
javaType:填寫集合型別的名稱
-->
<collection property="orders" javaType="list" ofType="order">
<!-- 配置主鍵,是關聯Order的唯一標識 -->
<id property="id" column="oid" />
<result property="number" column="number" />
<result property="createtime" column="createtime" />
<result property="note" column="note" />
</collection>
</resultMap> 3)呼叫例項:
<!-- 一對多關聯,查詢訂單同時查詢該使用者下的訂單 -->
<select id="queryUserOrder" resultMap="userOrderResultMap">
SELECT
u.id,
u.username,
u.birthday,
u.sex,
u.address,
o.id oid,
o.number,
o.createtime,
o.note
FROM
`user` u
LEFT JOIN `order` o ON u.id = o.user_id
</select>

動態SQL


簡介

主要介紹Mybatis提供的幾種用於實現動態SQL的標籤的基本使用方式:

  • if
  • choose、when、otherwise
  • trim、where、set
  • foreach

if

if 語句提供了可選的查詢文字功能

若 if 中條件成立,則執行 if 標籤中的語句,拼接至SQL語句中

若 if 中條件不成立,則忽略,舉個栗子:

<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = 'ACTIVE'
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>

choose、when、otherwise

Mybatis提供的choose元素,類似Java的switch語句,可從多個條件中選擇一個使用

舉個栗子:傳入了"title"就按"title"查詢,傳入了"author"就按"author"查詢的情形。

若兩者都沒有傳入,就返回標記為featured=1的BLOG(若多個條件滿足則遵循就近原則)

<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = 'ACTIVE'
<choose>
<when test="title !=null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>

trim、where、set

where

如何將上例中的"state='ACTIVE'"條件設定為動態條件,即WHERE標籤

<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
WHERE
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>

按上面所寫,如果沒有匹配的條件,SQL會變成:

SELECT * FROM BLOG
WHERE

導致查詢失敗。如果匹配的只是第二/三個條件,SQL會變成:

SELECT * FROM BLOG
WHERE
AND title like 'title'

從上例可看出 WHERE 語句後的第一個條件想要實現動態SQL不能簡單使用條件元素來解決,對此可以使用Mybatis提供的where元素

<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>

where元素只會在子元素返回任何內容的情況下才插入"WHERE"子句。並且若子句的開頭為"AND"或"OR",where元素也會將它們去除

set

用於動態更新語句的類似解決方案叫set。set元素可以用於動態包含需要更新的列,忽略其他不更新的列,比如:

<update id="updateAuthorIfNecessary">
UPDATE Author
<set>
<if test="username != null">
username=#{username},
</if>
<if test="password != null">
password=#{password},
</if>
<if test="email != null">
email=#{email},
</if>
<if test="bio != null">
bio=#{bio}
</if>
</set>
where id = #{id}
</update>

trim

如果選擇的元素與你期望的不大一樣,可以通過自定義trim元素來制定元素的功能,比如:

where標籤:

<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>

set標籤:

<trim prefix="set" suffixOverrides=",">
...
</trim>

prefix:字首

prefixOverrides:字首覆蓋,忽略通過管道符分隔的文字序列

suffixOverrides:字尾覆蓋,覆蓋了字尾值的設定

foreach

動態SQL的另一個常見使用場景是對集合進行遍歷(尤其是在構建IN條件語句的時候)

<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>

可以將任何可迭代物件(List, Set)、Map或陣列物件作為集合引數傳遞給foreach。當使用可迭代物件或者陣列時,index是當前迭代的序號,item的值是本次迭代獲取到的元素。使用Map物件時,index是key,item是value