Java-Mybatis動態SQL整理


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





免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM