MyBatis 多條件查詢、動態SQL、多表操作、註解開發,應有盡有,一網打盡!

來源:iyu77.blog.csdn.net/article/details/125761737

MyBatis封裝了JDBC通過Mapper代理的方式,以前繁瑣的操作通過“屬性與字段映射”就簡單化解,MyBatis的動態SQL完美展現了DBMS的獨特魅力

一、多條件查詢

基於Mybatis的多條件查詢,是在Mapper代理的映射文件中寫上原有的SQL,然後接口中寫一個帶參的方法即可,就像這樣:

相比於原生的JDBC那一套,通過MyBatis確實解決了不少硬編碼的問題

但是用戶的查詢永遠是動態的操作,他可能在多個條件中選擇其中少量條件進行查詢,我們的SQL是死的,而用戶需求對應的SQL卻是活的,這樣就會造成不匹配而形成語法錯誤

比如,根據這張表,若是要根據部分字段查出整體,我們可以寫對應需求的SQL,但是我要是查詢的條件變少了或者變多了呢?若用戶只想通過一個條件來查詢,那麼在其他佔位符的位置不輸入於是成了null,過不了語法自然查不了,還得重新寫SQL,多麻煩

這個時候MyBatis的特色就體現出來了——動態SQL

二、動態SQL

SQL語句會隨着用戶的輸入或者外部條件的變化而變化,則稱之爲動態SQL

1. if-where

因爲採用了Mapper代理開發,我們可以通過寫xml的形式來編寫我們的SQL,動態SQL的特性也就在這一舉動中所蘊育,在原有的Mapper文件裏我們進行如下改造,讓平平無奇的SQL煥然一新:

<select id="selByCondition" resultMap="rm">
    select *
    from mybatis
    <where>
    <if test="status !=null">
       and STATUS=#{STATUS}
    </if>
    <if test="companyName !=null and companyName !=''">
    and company_name like #{companyName}
    </if>
    <if test="bracdName !=null and bracdName !=''">
    and bracd_name like #{bracdName}
    </if>
    </where>
</select>

<where>標籤可以自動幫我們去掉and”,這樣,不管查詢的條件怎麼變,我跟着這個邏輯流程走就不會出現SQL語法毛病而導致查詢不出來的毛病啦,因爲null的情況已經被if所過濾掉了,真是太哇塞了!

推薦一個開源免費的 Spring Boot 最全教程:

https://github.com/javastacks/spring-boot-best-practice

2. choose-when-ortherwise

對於從多個條件中選擇一個的單條件查詢的場景,利用分支嵌套就可以實現動態選擇單條件:

在MyBatis的Mapper代理中,<choose>相當於switch,<when>相當於case

<select id="selByCondition2" resultMap="rm">
    select *
    from mybatis where
    <choose>
        <when test="status !=null">
            STATUS=#{STATUS}
        </when>
        <when test="companyName !=null and companyName !=''">
            company_name like #{companyName}
        </when>
        <when test="bracdName !=null and bracdName !=''">
            bracd_name like #{bracdName}
        </when>
        <otherwise>1=1</otherwise>
    </choose>
</select>

與多條件查詢不同的是,SQL語句中只會有一個分支生效

當用戶一個條件都不選時,可以在<otherwise>中寫上1=1讓語法成立,反之,若選擇了條件則會返回正常結果

3. foreach

對於批量刪除的場景,傳統的方法是通過in關鍵字結合佔位符來確定,就像這樣

where id in (?,?,?)

但對於動態的場景,批量的數量永遠是不確定的,這就導致還需要去改SQL裏的佔位符數量啊,又是一件麻煩事

PS:MyBatis會將數組參數封裝成一個Map集合,默認情況(K-V)array=數組

下面使用了@Param註解改變了map集合中默認的key

於是MyBatis中的<foreach>解決了這一麻煩:

本質是通過遍歷的形式,批量刪除的數據是由id數組或者集合來決定,collection屬性決定了要遍歷哪個數組/集合,item屬性則來存放選出的元素,並把它放在佔位符裏,separator屬性表示分隔符

<delete id="deleteById">
    delete frpm mybatis where id in
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>;
</delete>

有人會問爲啥這裏只有一個#{id},我的屬性字段不止這一個呀?此id非彼id他是一個數組/集合

三、多表操作

多表之間的關係有一對一,一對多,多對一,多對多,每一種都有建表的原則,以用戶-訂單模型爲例

利用傳統的方法進行多表查詢無非是通過id來連接表然後封裝返回結果,MyBatis中也是如此,我們在Mapper文件中寫好表字段之間的映射關係,定義好類型即可,只不過這一過程有點複雜,但一次配好之後即可極大減少硬編碼問題,提高效率

1. 一對一

一個用戶有一張訂單

首先還是那套路,建好實體類,寫好接口方法,配置Mapper文件,而多表操作的麻煩點就在於配置文件,這裏通過例子細說一下

1.先把表寫好
CREATE TABLE orders (
id INT PRIMARY KEY ,
ordertime VARCHAR(20) NOT NULL DEFAULT '',
total DOUBLE,
uid INT);
INSERT INTO orders VALUES(1,2020,2000,1);
INSERT INTO orders VALUES(2,2021,3000,2);
INSERT INTO orders VALUES(3,2022,4000,3);
CREATE TABLE USER (
id INT PRIMARY KEY ,
username VARCHAR(50) NOT NULL DEFAULT '',
passwords VARCHAR(50) NOT NULL DEFAULT '');
INSERT INTO USER VALUES(1,'lyy',333);
INSERT INTO USER VALUES(2,'myy',444);
INSERT INTO USER VALUES(3,'xyy',555);
2.寫Mapper配置文件

在寫實體類時,要把一個實體寫到另一個實體的屬性裏面,這樣才體現關聯性,就比如“訂單是所用戶擁有的”,正因爲這種關係我們纔會在訂單實體類裏面寫上private User user;這一屬性,這樣根據id連接的兩個實體才能完美對接!

就像這樣:

通過<association>把兩張表對應的實體類連接起來,只不過是主鍵ID要用單獨的標籤

  • property: 當前實體(order)中的屬性名稱(private User user)
  • javaType: 當前實體(order)中的屬性的類型(User)

這兩個user有着本質上的卻別,就好像前者是在一個人的名字,後者正是被叫的那個人,MyBatis好像就利用了這一特性,通過標籤的形式連接了兩個實體

<select id="findAll" resultMap="orderMap">
   SELECT *,o.id oid FROM orders o,USER u WHERE o.uid=u.id
</select>

SQL環節和原來沒什麼區別,同樣也是通過resultMap把字段和屬性映射封裝。

2.一對多

一個用戶有多張訂單

首先,在原有的User實體中得加上一個表示“用戶有哪些訂單的屬性”private List<Order> orderList;,目的是爲了把訂單的信息封裝到用戶的這個屬性裏,在Mapper文件中體現:

<collection property="orderList" ofType="order">
    <!--封裝order的數據-->
    <id column="oid" property="id"></id>
    <result column="ordertime" property="ordertime"></result>
    <result column="total" property="total"></result>
</collection>
  • property:集合名稱,User實體中的orderlist屬性
  • ofType:當前集合中的數據類型,就是order實體

然後就是寫一對多的SQL:

<select id="findAll" resultMap="userMap">
   SELECT *,o.id oid FROM USER u,orders o WHERE u.id=o.uid
</select>

總結來看,一對多相比於一對一就是在那個“一”中增添了封裝“多”的屬性而已,然後稍微調整一下SQL

3.多對多

多用戶多角色

多對多的建表原則是引入一張中間表,用於維護外鍵,就是一張表通過中間表找到另一張表

和一對多的模型類似,先在User實體類中增添一個“用戶具備哪些角色”的屬性private List roleList;其次配置Mapper文件:

<collection property="roleList" ofType="role">
   <id column="roleId" property="id"></id>
   <result column="roleName" property="roleName"></result>
   <result column="roleDesc" property="roleDesc"></result>
</collection>

多表的連接是靠中間表,這點在Mapper文件中通過映射實現,具體是把兩張外表的id(userId和roleId)在id標籤中配置成同一個屬性,就像這樣:

<id column="userId" property="id"></id>
<id column="roleId" property="id"></id>

SQL環節就得用多對多的套路了

<select id="findUserAndRoleAll" resultMap="userRoleMap">
    SELECT * FROM USER u,user-role ur,role r WHERE u.id=ur.userId AND ur.roleId=r.id
</select>

回想進行多表操作時MyBatis爲我們帶來了什麼?他確實減少了很多硬編碼,我每一次新的SQL只需要在標籤裏改幾個屬性就可以,只要理清字段與屬性的映射關係,在MyBatis中進行多表操作就是一個“對號入座”。

四、註解開發

針對於簡單的CRUD註解開發可以極大地提升效率,顧名思義就是把SQL寫在註解裏

查詢(@Select):

添加(@Insert):

修改(@Update):

刪除(@Delete) :

近期熱文推薦:

1.1,000+ 道 Java面試題及答案整理(2022最新版)

2.勁爆!Java 協程要來了。。。

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這纔是優雅的方式!!

5.《Java開發手冊(嵩山版)》最新發布,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!

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