Mybatis高級應用(上)

首先聲明。該Mybatis系列的博客是我學習性博客,整個系列的博客是需要連貫起來看的。總結也是片段性總結的。如果覺得有些思維跳躍,或不連貫請參考代碼。

本項目所有代碼及文檔都託管在 Github地址:https://github.com/JYG0723/mybatispractice

如果覺得不錯的話,歡迎給個 star , 如果你想完善這個項目的話,你也可以 fork 後修改然後推送給我。


動態 SQL

通過mybatis提供的各種標籤方法實現動態拼接sql。

對查詢條件進行判斷,如果輸入的參數不爲空才進行查詢條件拼接。

public class Customer {

    private int id;
    private String username;
    private String password;
    private User user;

}
public interface CustomerDao {

    public Customer findCustomerById(int id);

    public Customer findCustomerByCustomer(@Param(value = "customer") Customer customer);//指定傳入到xml配置文件中的參數的使用名稱

}
<select id="findCustomerByCustomer" parameterType="Customer" resultType="Customer">
        SELECT * FROM customer
        <where><!-- where 1=1 -->
            <if test="customer.user != null"><!--用到java屬性進行判斷的地方,全名稱引用避免參數找不到錯誤-->
                <if test="customer.user.password != null and customer.user.password != ''">
                    AND password = #{customer.user.password}
                </if>
                <if test="customer.user.username !=null and customer.user.username !=''">
                    AND username LIKE '%${customer.user.username}%'<!--自動忽略第一個通過條件判斷接入的sql語句的 'and' 拼接前綴。-->
                </if>
            </if>
        </where>
</select>

Sql 片段

通過上面的其實看到在 where sql語句中有很多重複代碼,可以將其抽取出來,組成一個sql片段,其他的statement就可以引用這個sql片段,利於系統的開發。

這裏我們就拿上邊sql 中的where定義一個sq片段如下:

select * from user
        <where>
        <!--refid: 指定sql片段的id,如果是寫在其他的mapper文件中,則需要在前面加上namespace-->
            <include refid="query_user_where"/>
        </where>

selectKey useGeneratedKeys

插入更新一條數據時,可以使用selectKey獲取id操作。當做多條數據插入更新時,而selectKey只能使用一次,此時應該使用useGeneratedKeys操作。

selectKey:

<insert id="insert">
 <selectKey keyProperty="id" resultType="int" order="BEFORE">
  <if test="_databaseId == 'oracle'">
   select seq_users.nextval from dual
  </if>
  <if test="_databaseId == 'db2'">
   select nextval for seq_users from sysibm.sysdummy1"
  </if>
 </selectKey>
 insert into users values (#{id}, #{name})
</insert>

useGeneratedKeys:

<insert id="insertAuthor" useGeneratedKeys="true" keyProperty="id">
    insert into Author (username,password,email,bio)
    values (#{username},#{password},#{email},#{bio})
</insert>

typeAliases

 <typeAliases>
        <typeAlias alias="User" type="po.User"/>
        <typeAlias alias="Customer" type="po.Customer"/>
        <!--
             <package napobean"></package>     包下的所有類的別名爲他們的類名
        -->
        <typeAlias type="po.Orders" alias="Orders"/>
        <typeAlias type="po.OrdersUser" alias="OrdersUser"/>
        <typeAlias type="po.Items" alias="Items"/>
        <typeAlias type="po.Orderdetail" alias="Orderdetail"/>
        <typeAlias type="hashMap" alias="java.util.HashMap"/>
    </typeAliases>

foreach

<if test="ids!=null">
<!-- 使用 foreach遍歷傳入ids
collection:指定輸入 對象中集合屬性
item:每個遍歷實體的名稱
open:開始遍歷時拼接的串
close:結束遍歷時拼接的串
separator:遍歷的兩個對象中需要拼接的串
-->

<!-- 使用實現下邊的sql拼接:
       AND (id=1 OR id=10 OR id=16) 
-->
            <foreach collection="ids" item="user_id" open="AND (" close=")" separator="or">
                <!-- 每個遍歷需要拼接的串 -->
                id=#{user_id}
            </foreach>

            <!-- 實現  “ and id IN(1,10,16)”拼接 -->
            <!-- <foreach collection="ids" item="user_id" open="and id IN(" close=")" separator=",">               
                每個遍歷需要拼接的串
                #{user_id}
            </foreach> -->
</if>

要做foreach的對象,作爲入參時,List

使用 resultType 和 resultMap 一對一查詢小結

使用 resultMap 將查詢結果中的訂單信息映射到 Orders 對象中,在 orders 類中添加 User 屬性,將關聯查詢出來的用戶信息映射到 orders 對象中的 user 屬性中。使用 resultMap 將查詢結果中的訂單信息映射到 Orders 對象中,在 orders 類中添加 User 屬性,將關聯查詢出來的用戶信息映射到 orders 對象中的 user 屬性中。

使用 resultType 將查詢結果中的訂單信息映射到 OrdersUser 對象中,因爲該OrdersUser對象繼承了Orders實體類,所以訂單信息便可以映射到OrdersUser對象中。同時爲該OrdersUser對象添加User實體的特有屬性,同時將查詢到的User屬性映射到該類中。

  • resultType:使用resultType實現較爲簡單,如果pojo中沒有包括查詢出來的列名,需要增加列名對應的屬性,即可完成映射。如果沒有查詢結果的特殊要求建議使用resultType。
  • resultMap:需要單獨定義resultMap,實現有點麻煩,如果對查詢結果有特殊的要求,使用resultMap可以完成將關聯查詢映射pojo的屬性中。resultMap可以實現延遲加載,resultType無法實現延遲加載。

一對多查詢

mybatis使用resultMap的collection對關聯查詢的多條記錄映射到一個list集合屬性中。

使用resultType實現:將訂單明細映射到orders中的orderdetails中,需要自己處理,使用雙重循環遍歷,去掉重複記錄,將訂單明細放在orderdetails中。

多對多查詢總結

將查詢用戶購買的商品信息明細清單,(用戶名、用戶地址、購買商品名稱、購買商品時間、購買商品數量)

針對上邊的需求就使用resultType將查詢到的記錄映射到一個擴展的pojo中,很簡單實現明細清單的功能。

一對多是多對多的特例,如下需求:

查詢用戶購買的商品信息,用戶和商品的關係是多對多關係。

需求1:

查詢字段:用戶賬號、用戶名稱、用戶性別、商品名稱、商品價格(最常見)
企業開發中常見明細列表,用戶購買商品明細列表,
使用resultType將上邊查詢列映射到pojo輸出。

需求2:

查詢字段:用戶賬號、用戶名稱、購買商品數量、商品明細(鼠標移上顯示明細)
使用resultMap將用戶購買的商品明細列表映射到user對象中。

總結:

使用resultMap是針對那些對查詢結果映射有特殊要求的功能,比如特殊要求映射成的list中包括多個list。查詢多表字段,不易用resultType實現的時候使用。

ResultMap 總結

resultType:
作用:

將查詢結果按照sql列名pojo屬性名一致性映射到pojo中。
場合:常見一些明細記錄的展示,比如用戶購買商品明細,將關聯查詢信息全部展示在頁面時,此時可直接使用resultType將每一條記錄映射到pojo中,在前端頁面遍歷list(list中是pojo)即可。

resultMap:
作用:

使用association和collection完成一對一和一對多高級映射(對結果有特殊的映射要求)。

association:
作用:

將關聯查詢信息映射到一個pojo對象中。
場合:爲了方便查詢關聯信息可以使用association將關聯訂單信息映射爲用戶對象的pojo屬性中,比如:查詢訂單及關聯用戶信息。
使用resultType無法將查詢結果映射到pojo對象的pojo屬性中,根據對查詢出的結果集查詢並遍歷匹配時的需要選擇使用resultType還是resultMap。

collection:
作用:

將關聯查詢信息映射到一個list集合中。
場合:爲了方便查詢遍歷關聯信息可以使用collection將關聯信息映射到list集合中,比如:查詢用戶權限範圍模塊及模塊下的菜單,可使用collection將模塊映射到模塊list中,將菜單列表映射到模塊對象的菜單list屬性中,這樣的作的目的也是方便對查詢結果集進行遍歷查詢。如果使用resultType無法將查詢結果映射到list集合中的時候。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章