<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          MyBatis多條件查詢(xún)、動(dòng)態(tài)SQL、多表操作、注解開(kāi)發(fā)詳細(xì)教程

          共 7622字,需瀏覽 16分鐘

           ·

          2022-08-26 17:55

          點(diǎn)擊關(guān)注公眾號(hào),Java干貨及時(shí)送達(dá)??

          來(lái)源:iyu77.blog.csdn.net/article/details/125761737

          • 一、多條件查詢(xún)
          • 二、動(dòng)態(tài)SQL
            • 1.if-where
            • 2.choose-when-ortherwise
            • 3.foreach
          • 三、多表操作
            • 1.一對(duì)一
            • 2.一對(duì)多
            • 3.多對(duì)多
          • 四、注解開(kāi)發(fā)

          MyBatis封裝了JDBC通過(guò)Mapper代理的方式,以前繁瑣的操作通過(guò)“屬性與字段映射”就簡(jiǎn)單化解,MyBatis的動(dòng)態(tài)SQL完美展現(xiàn)了DBMS的獨(dú)特魅力

          一、多條件查詢(xún)

          基于Mybatis的多條件查詢(xún),是在Mapper代理的映射文件中寫(xiě)上原有的SQL,然后接口中寫(xiě)一個(gè)帶參的方法即可,就像這樣:

          圖片

          相比于原生的JDBC那一套,通過(guò)MyBatis確實(shí)解決了不少硬編碼的問(wèn)題

          但是用戶(hù)的查詢(xún)永遠(yuǎn)是動(dòng)態(tài)的操作,他可能在多個(gè)條件中選擇其中少量條件進(jìn)行查詢(xún),我們的SQL是死的,而用戶(hù)需求對(duì)應(yīng)的SQL卻是活的,這樣就會(huì)造成不匹配而形成語(yǔ)法錯(cuò)誤

          比如,根據(jù)這張表,若是要根據(jù)部分字段查出整體,我們可以寫(xiě)對(duì)應(yīng)需求的SQL,但是我要是查詢(xún)的條件變少了或者變多了呢?若用戶(hù)只想通過(guò)一個(gè)條件來(lái)查詢(xún),那么在其他占位符的位置不輸入于是成了null,過(guò)不了語(yǔ)法自然查不了,還得重新寫(xiě)SQL,多麻煩

          圖片

          這個(gè)時(shí)候MyBatis的特色就體現(xiàn)出來(lái)了——?jiǎng)討B(tài)SQL

          二、動(dòng)態(tài)SQL

          SQL語(yǔ)句會(huì)隨著用戶(hù)的輸入或者外部條件的變化而變化,則稱(chēng)之為動(dòng)態(tài)SQL

          1.if-where

          因?yàn)椴捎昧薓apper代理開(kāi)發(fā),我們可以通過(guò)寫(xiě)xml的形式來(lái)編寫(xiě)我們的SQL,動(dòng)態(tài)SQL的特性也就在這一舉動(dòng)中所蘊(yùn)育,在原有的Mapper文件里我們進(jìn)行如下改造,讓平平無(wú)奇的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>標(biāo)簽可以自動(dòng)幫我們?nèi)サ鬭nd”,這樣,不管查詢(xún)的條件怎么變,我跟著這個(gè)邏輯流程走就不會(huì)出現(xiàn)SQL語(yǔ)法毛病而導(dǎo)致查詢(xún)不出來(lái)的毛病啦,因?yàn)閚ull的情況已經(jīng)被if所過(guò)濾掉了,真是太哇塞了!

          2.choose-when-ortherwise

          對(duì)于從多個(gè)條件中選擇一個(gè)的單條件查詢(xún)的場(chǎng)景,利用分支嵌套就可以實(shí)現(xiàn)動(dòng)態(tài)選擇單條件:

          在MyBatis的Mapper代理中,<choose>相當(dāng)于switch,<when>相當(dāng)于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>

          與多條件查詢(xún)不同的是,SQL語(yǔ)句中只會(huì)有一個(gè)分支生效

          當(dāng)用戶(hù)一個(gè)條件都不選時(shí),可以在<otherwise>中寫(xiě)上1=1讓語(yǔ)法成立,反之,若選擇了條件則會(huì)返回正常結(jié)果

          3.foreach

          對(duì)于批量刪除的場(chǎng)景,傳統(tǒng)的方法是通過(guò)in關(guān)鍵字結(jié)合占位符來(lái)確定,就像這樣

          where id in (?,?,?)

          但對(duì)于動(dòng)態(tài)的場(chǎng)景,批量的數(shù)量永遠(yuǎn)是不確定的,這就導(dǎo)致還需要去改SQL里的占位符數(shù)量啊,又是一件麻煩事

          PS:MyBatis會(huì)將數(shù)組參數(shù)封裝成一個(gè)Map集合,默認(rèn)情況(K-V)array=數(shù)組

          下面使用了@Param注解改變了map集合中默認(rèn)的key

          圖片

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

          本質(zhì)是通過(guò)遍歷的形式,批量刪除的數(shù)據(jù)是由id數(shù)組或者集合來(lái)決定,collection屬性決定了要遍歷哪個(gè)數(shù)組/集合,item屬性則來(lái)存放選出的元素,并把它放在占位符里,separator屬性表示分隔符

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

          有人會(huì)問(wèn)為啥這里只有一個(gè)#{id},我的屬性字段不止這一個(gè)呀?此id非彼id他是一個(gè)數(shù)組/集合

          三、多表操作

          多表之間的關(guān)系有一對(duì)一,一對(duì)多,多對(duì)一,多對(duì)多,每一種都有建表的原則,以用戶(hù)-訂單模型為例

          利用傳統(tǒng)的方法進(jìn)行多表查詢(xún)無(wú)非是通過(guò)id來(lái)連接表然后封裝返回結(jié)果,MyBatis中也是如此,我們?cè)贛apper文件中寫(xiě)好表字段之間的映射關(guān)系,定義好類(lèi)型即可,只不過(guò)這一過(guò)程有點(diǎn)復(fù)雜,但一次配好之后即可極大減少硬編碼問(wèn)題,提高效率

          1.一對(duì)一

          一個(gè)用戶(hù)有一張訂單

          首先還是那套路,建好實(shí)體類(lèi),寫(xiě)好接口方法,配置Mapper文件,而多表操作的麻煩點(diǎn)就在于配置文件,這里通過(guò)例子細(xì)說(shuō)一下

          1.先把表寫(xiě)好
          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.寫(xiě)Mapper配置文件

          在寫(xiě)實(shí)體類(lèi)時(shí),要把一個(gè)實(shí)體寫(xiě)到另一個(gè)實(shí)體的屬性里面,這樣才體現(xiàn)關(guān)聯(lián)性,就比如“訂單是所用戶(hù)擁有的”,正因?yàn)檫@種關(guān)系我們才會(huì)在訂單實(shí)體類(lèi)里面寫(xiě)上private User user;這一屬性,這樣根據(jù)id連接的兩個(gè)實(shí)體才能完美對(duì)接!

          就像這樣:

          通過(guò)<association>把兩張表對(duì)應(yīng)的實(shí)體類(lèi)連接起來(lái),只不過(guò)是主鍵ID要用單獨(dú)的標(biāo)簽

          • property: 當(dāng)前實(shí)體(order)中的屬性名稱(chēng)(private User user)
          • SQLType: 當(dāng)前實(shí)體(order)中的屬性的類(lèi)型(User)

          這兩個(gè)user有著本質(zhì)上的卻別,就好像前者是在一個(gè)人的名字,后者正是被叫的那個(gè)人,MyBatis好像就利用了這一特性,通過(guò)標(biāo)簽的形式連接了兩個(gè)實(shí)體

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

          SQL環(huán)節(jié)和原來(lái)沒(méi)什么區(qū)別,同樣也是通過(guò)resultMap把字段和屬性映射封裝

          2.一對(duì)多

          一個(gè)用戶(hù)有多張訂單

          圖片

          首先,在原有的User實(shí)體中得加上一個(gè)表示“用戶(hù)有哪些訂單的屬性”private List<Order> orderList;,目的是為了把訂單的信息封裝到用戶(hù)的這個(gè)屬性里,在Mapper文件中體現(xiàn):

          <collection property="orderList" ofType="order">
              <!--封裝order的數(shù)據(jù)-->
              <id column="oid" property="id"></id>
              <result column="ordertime" property="ordertime"></result>
              <result column="total" property="total"></result>
          </collection>
          • property:集合名稱(chēng),User實(shí)體中的orderlist屬性
          • ofType:當(dāng)前集合中的數(shù)據(jù)類(lèi)型,就是order實(shí)體

          然后就是寫(xiě)一對(duì)多的SQL:

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

          總結(jié)來(lái)看,一對(duì)多相比于一對(duì)一就是在那個(gè)“一”中增添了封裝“多”的屬性而已,然后稍微調(diào)整一下SQL

          3.多對(duì)多

          多用戶(hù)多角色

          圖片

          多對(duì)多的建表原則是引入一張中間表,用于維護(hù)外鍵,就是一張表通過(guò)中間表找到另一張表

          和一對(duì)多的模型類(lèi)似,先在User實(shí)體類(lèi)中增添一個(gè)“用戶(hù)具備哪些角色”的屬性private List<Role> 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>

          多表的連接是靠的中間表,這點(diǎn)在Mapper文件中通過(guò)映射實(shí)現(xiàn),具體是把兩張外表的id(userId和roleId)在id標(biāo)簽中配置成同一個(gè)屬性,就像這樣:

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

          SQL環(huán)節(jié)就得用多對(duì)多的套路了

          <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>

          回想進(jìn)行多表操作時(shí)MyBatis為我們帶來(lái)了什么?他確實(shí)減少了很多硬編碼,我每一次新的SQL只需要在標(biāo)簽里改幾個(gè)屬性就可以,只要理清字段與屬性的映射關(guān)系,在MyBatis中進(jìn)行多表操作就是一個(gè)“對(duì)號(hào)入座”

          四、注解開(kāi)發(fā)

          針對(duì)于簡(jiǎn)單的CRUD注解開(kāi)發(fā)可以極大地提升效率,顧名思義就是把SQL寫(xiě)在注解里

          查詢(xún)(@Select):

          圖片

          添加(@Insert):

          圖片

          修改(@Update):

          圖片

          刪除(@Delete) :

          圖片

          1. 面試官:Java 序列化和反序列化為什么要實(shí)現(xiàn) Serializable 接口?

          2. 別再用currentTimeMillis統(tǒng)計(jì)耗時(shí)了,太 Low,試試StopWatch吧!

          3. Nacos 2.1.1 正式發(fā)布,真心強(qiáng)!

          4. 萬(wàn)能通用!權(quán)限系統(tǒng)就該這么設(shè)計(jì)

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          PS:因公眾號(hào)平臺(tái)更改了推送規(guī)則,如果不想錯(cuò)過(guò)內(nèi)容,記得讀完點(diǎn)一下在看,加個(gè)星標(biāo),這樣每次新文章推送才會(huì)第一時(shí)間出現(xiàn)在你的訂閱列表里。

          點(diǎn)“在看”支持小哈呀,謝謝啦

          瀏覽 24
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  c逼视频网站 | 国产精品内射婷婷 | 一区二区三区国产 | 欧美三级全黄做爰大尺 | 国产成人精品一区二区 |