0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

MyBatis動(dòng)態(tài)sql是什么?MyBatis動(dòng)態(tài)SQL最全教程

jf_ro2CN3Fa ? 來(lái)源:CSDN ? 2023-08-10 10:18 ? 次閱讀

一、MyBatis動(dòng)態(tài) sql 是什么

動(dòng)態(tài) SQL 是 MyBatis 的強(qiáng)大特性之一。在 JDBC 或其它類似的框架中,開(kāi)發(fā)人員通常需要手動(dòng)拼接 SQL 語(yǔ)句。根據(jù)不同的條件拼接 SQL 語(yǔ)句是一件極其痛苦的工作。例如,拼接時(shí)要確保添加了必要的空格,還要注意去掉列表最后一個(gè)列名的逗號(hào)。而動(dòng)態(tài) SQL 恰好解決了這一問(wèn)題,可以根據(jù)場(chǎng)景動(dòng)態(tài)的構(gòu)建查詢。

動(dòng)態(tài)SQL(code that is executed dynamically),它一般是根據(jù)用戶輸入或外部條件動(dòng)態(tài)組合的SQL語(yǔ)句塊。 動(dòng)態(tài)SQL能靈活的發(fā)揮SQL強(qiáng)大的功能、方便的解決一些其它方法難以解決的問(wèn)題。 相信使用過(guò)動(dòng)態(tài)SQL的人都能體會(huì)到它帶來(lái)的便利,然而動(dòng)態(tài)SQL有時(shí)候在執(zhí)行性能 (效率)上面不如靜態(tài)SQL,而且使用不恰當(dāng),往往會(huì)在安全方面存在隱患 (SQL 注入式攻擊)。

1.Mybatis 動(dòng)態(tài) sql 是做什么的?

Mybatis 動(dòng)態(tài) sql 可以讓我們?cè)?Xml 映射文件內(nèi),以標(biāo)簽的形式編寫動(dòng)態(tài) sql,完成邏輯判斷和動(dòng)態(tài)拼接 sql 的功能。

2.Mybatis 的 9 種 動(dòng) 態(tài) sql 標(biāo) 簽有哪些?

元素 作用 備注
if 判斷語(yǔ)句 單條件分支判斷
choose(when、otherwise) 相當(dāng)于 Java 中的 switch case 語(yǔ)句 多條件分支判斷
trim,where 輔助元素 用于處理一些SQL拼裝問(wèn)題
foreach 循環(huán)語(yǔ)句 在in語(yǔ)句等列舉條件常用
bind 輔助元素 拼接參數(shù)

3.動(dòng)態(tài) sql 的執(zhí)行原理?

原理為:使用 OGNL 從 sql 參數(shù)對(duì)象中計(jì)算表達(dá)式的值,根據(jù)表達(dá)式的值動(dòng)態(tài)拼接 sql,以此來(lái)完成動(dòng)態(tài) sql 的功能。

二、MyBatis標(biāo)簽

1.if標(biāo)簽:條件判斷

MyBatis if 類似于 Java 中的 if 語(yǔ)句,是 MyBatis 中最常用的判斷語(yǔ)句。使用 if 標(biāo)簽可以節(jié)省許多拼接 SQL 的工作,把精力集中在 XML 的維護(hù)上。

1)不使用動(dòng)態(tài)sql


 
select*fromuserwhereusername=#{username}andsex=#{sex}

if 語(yǔ)句使用方法簡(jiǎn)單,常常與 test 屬性聯(lián)合使用。語(yǔ)法如下:

SQL語(yǔ)句

2)使用動(dòng)態(tài)sql

上面的查詢語(yǔ)句,我們可以發(fā)現(xiàn),如果 #{username} 為空,那么查詢結(jié)果也是空,如何解決這個(gè)問(wèn)題呢?使用 if 來(lái)判斷,可多個(gè) if 語(yǔ)句同時(shí)使用。

以下語(yǔ)句表示為可以按照網(wǎng)站名稱(name)或者網(wǎng)址(url)進(jìn)行模糊查詢。如果您不輸入名稱或網(wǎng)址,則返回所有的網(wǎng)站記錄。但是,如果你傳遞了任意一個(gè)參數(shù),它就會(huì)返回與給定參數(shù)相匹配的記錄。


selectid,name,urlfromwebsite
where1=1

ANDnamelike#{name}


ANDurllike#{url}


2.where+if標(biāo)簽

where、if同時(shí)使用可以進(jìn)行查詢、模糊查詢

注意,失敗后, 關(guān)鍵字只會(huì)去掉庫(kù)表字段賦值前面的and,不會(huì)去掉語(yǔ)句后面的and關(guān)鍵字,即注意, 只會(huì)去掉 語(yǔ)句中的最開(kāi)始的and關(guān)鍵字。所以下面的形式是不可取的





sacclikeconcat('%'#{sacc}'%')


ANDsnamelikeconcat('%'#{sname}'%')


ANDsex=#{sex}


ANDphone=#{phone}



這個(gè)“where”標(biāo)簽會(huì)知道如果它包含的標(biāo)簽中有返回值的話,它就插入一個(gè)‘where’。此外,如果標(biāo)簽返回的內(nèi)容是以AND 或OR 開(kāi)頭的,則它會(huì)剔除掉。

3.set標(biāo)簽

set可以用來(lái)修改


updatestudent

sname=#{sname},
spwd=#{spwd},
sex=#{sex},
phone=#{phone}
sid=#{sid}

wheresid=#{sid}

4.choose(when,otherwise) 語(yǔ)句

有時(shí)候,我們不想用到所有的查詢條件,只想選擇其中的一個(gè),查詢條件有一個(gè)滿足即可,使用 choose 標(biāo)簽可以解決此類問(wèn)題,類似于 Java 的 switch 語(yǔ)句


select*fromuser



id=#{id}


andusername=#{username}


andsex=#{sex}




也就是說(shuō),這里我們有三個(gè)條件,id、username、sex,只能選擇一個(gè)作為查詢條件

如果 id 不為空,那么查詢語(yǔ)句為:select * from user where id=?

如果 id 為空,那么看username 是否為空,如果不為空,那么語(yǔ)句為 select * from user where username=?;

如果 username 為空,那么查詢語(yǔ)句為 select * from user where sex=?

5.trim

trim標(biāo)記是一個(gè)格式化的標(biāo)記,可以完成set或者是where標(biāo)記的功能

①、用 trim 改寫上面第二點(diǎn)的 if+where 語(yǔ)句


select*fromuser
 


andusername=#{username}


andsex=#{sex}



prefix:前綴

prefixoverride:去掉第一個(gè)and或者是or

②、用 trim 改寫上面第三點(diǎn)的 if+set 語(yǔ)句

 

updateuseru
 


u.username=#{username},


u.sex=#{sex},



whereid=#{id}

suffix:后綴

suffixoverride:去掉最后一個(gè)逗號(hào)(也可以是其他的標(biāo)記,就像是上面前綴中的and一樣)

③、trim+if同時(shí)使用可以添加


insertintostudent

sname,
spwd,
sex,
phone,



#{sname},
#{spwd},
#{sex},
#{phone}



6.MyBatis foreach標(biāo)簽

foreach是用來(lái)對(duì)集合的遍歷,這個(gè)和Java中的功能很類似。通常處理SQL中的in語(yǔ)句。

foreach 元素的功能非常強(qiáng)大,它允許你指定一個(gè)集合,聲明可以在元素體內(nèi)使用的集合項(xiàng)(item)和索引(index)變量。它也允許你指定開(kāi)頭與結(jié)尾的字符串以及集合項(xiàng)迭代之間的分隔符。這個(gè)元素也不會(huì)錯(cuò)誤地添加多余的分隔符

你可以將任何可迭代對(duì)象(如 List、Set 等)、Map 對(duì)象或者數(shù)組對(duì)象作為集合參數(shù)傳遞給 foreach。當(dāng)使用可迭代對(duì)象或者數(shù)組時(shí),index 是當(dāng)前迭代的序號(hào),item 的值是本次迭代獲取到的元素。當(dāng)使用 Map 對(duì)象(或者 Map.Entry 對(duì)象的集合)時(shí),index 是鍵,item 是值。

//批量查詢

WHEREsidin

#{ids}


//批量刪除

deletefromstudentwheresidin

#{ids}


整合案例

xml





select*fromstudent








WHERE1=1

ANDsidlike#{sid}







sacclikeconcat('%'#{sacc}'%')


ANDsnamelikeconcat('%'#{sname}'%')


ANDsex=#{sex}


ANDphone=#{phone}





updatestudent

sname=#{sname},
spwd=#{spwd},
sex=#{sex},
phone=#{phone}
sid=#{sid}

wheresid=#{sid}



insertintostudent

sname,
spwd,
sex,
phone,



#{sname},
#{spwd},
#{sex},
#{phone}




WHEREsidin

#{ids}




deletefromstudentwheresidin

#{ids}






測(cè)試類:

packagecom.yzx.test;

importcom.yzx.entity.Student;
importcom.yzx.mapper.StuMapper;
importorg.apache.ibatis.io.Resources;
importorg.apache.ibatis.session.SqlSession;
importorg.apache.ibatis.session.SqlSessionFactory;
importorg.apache.ibatis.session.SqlSessionFactoryBuilder;
importorg.junit.After;
importorg.junit.Before;
importorg.junit.Test;

importjava.io.IOException;
importjava.io.InputStream;
importjava.util.List;

publicclassStuTest{
SqlSessionsqlSession=null;
InputStreamis=null;

@Before
publicvoidbefore()throwsIOException{
//1.讀取核心配置文件
is=Resources.getResourceAsStream("sqlMapperConfig.xml");
//2.拿到工廠構(gòu)建類
SqlSessionFactoryBuildersqlSessionFactoryBuilder=newSqlSessionFactoryBuilder();
//3.拿到具體工廠
SqlSessionFactorybuild=sqlSessionFactoryBuilder.build(is);
//4.拿到session
sqlSession=build.openSession();
}

@After
publicvoidafter(){
//7,提交事務(wù)
sqlSession.commit();
//8.關(guān)閉資源
sqlSession.close();
if(is!=null){
try{
is.close();
}catch(IOExceptione){
e.printStackTrace();
}
};
}

//查詢所有
@Test
publicvoidfind(){
//5.獲取具體的mapper接口
StuMappermapper=sqlSession.getMapper(StuMapper.class);
//6.調(diào)用執(zhí)行
Listlist=mapper.find();
list.forEach(a->System.out.println(a));
}
//查詢單個(gè)
@Test
publicvoidfindbyid(){

StuMappermapper=sqlSession.getMapper(StuMapper.class);
Listlist=mapper.findbyid(2);
list.forEach(a->System.out.println(a));
}
//模糊查詢
@Test
publicvoidfindQuery(){

StuMappermapper=sqlSession.getMapper(StuMapper.class);

Studentstu=newStudent();
stu.setSname("小");
stu.setSex("男");
Listlist=mapper.findQuery(stu);
list.forEach(a->System.out.println(a));
}
//修改
@Test
publicvoidupd(){

StuMappermapper=sqlSession.getMapper(StuMapper.class);

Studentstu=newStudent();
stu.setSid(3);
stu.setSname("小若");
stu.setSex("人妖");
inti=mapper.upd(stu);
System.out.println("修改了"+i+"條數(shù)據(jù)"+""+stu.toString());

}
//添加
@Test
publicvoidadd(){

StuMappermapper=sqlSession.getMapper(StuMapper.class);

Studentstu=newStudent();
stu.setSname("小賀");
stu.setSex("男");
stu.setPhone("99999999");
inti=mapper.add(stu);
System.out.println("添加了"+i+"條數(shù)據(jù)"+""+stu.toString());

}

//批量操作
@Test
publicvoidfindAll(){

StuMappermapper=sqlSession.getMapper(StuMapper.class);
Integer[]i={1,2,3,4};
Listlist=mapper.findAll(i);
list.forEach(a->System.out.println(a));
}
//批量操作

//批量刪除
@Test
publicvoiddel(){
StuMappermapper=sqlSession.getMapper(StuMapper.class);
Integer[]i={1,2,3,4};
inti1=mapper.del(i);
System.out.println("刪除了"+i1+"條數(shù)據(jù)");
}
}

7.sql

在實(shí)際開(kāi)發(fā)中會(huì)遇到許多相同的SQL,比如根據(jù)某個(gè)條件篩選,這個(gè)篩選很多地方都能用到,我們可以將其抽取出來(lái)成為一個(gè)公用的部分,這樣修改也方便,一旦出現(xiàn)了錯(cuò)誤,只需要改這一處便能處處生效了,此時(shí)就用到了這個(gè)標(biāo)簽了。

當(dāng)多種類型的查詢語(yǔ)句的查詢字段或者查詢條件相同時(shí),可以將其定義為常量,方便調(diào)用。為求

9.如何引用其他XML中的SQL片段

比如你在com.xxx.dao.xxMapper這個(gè)Mapper的XML中定義了一個(gè)SQL片段如下:

ID,MAJOR,BIRTHDAY,AGE,NAME,HOBBY

此時(shí)我在com.xxx.dao.PatinetMapper中的XML文件中需要引用,如下:

三、MyBatis關(guān)聯(lián)查詢

1.MyBatis一對(duì)多關(guān)聯(lián)查詢

 












 

select*fromstudent1sleftjointeachertons.sid=t.sid

2.MyBatis多對(duì)一關(guān)聯(lián)查詢

 













 

select*fromteachertrightjoinstudent1sont.sid=s.sid

3.MyBatis多對(duì)多關(guān)聯(lián)查詢

 

select*fromstudent1sleftjoinrelevancerons.sid=r.sidleftjointeachertonr.tid=t.tid





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • SQL
    SQL
    +關(guān)注

    關(guān)注

    1

    文章

    751

    瀏覽量

    43985
  • JAVA語(yǔ)言
    +關(guān)注

    關(guān)注

    0

    文章

    138

    瀏覽量

    20055
  • XML技術(shù)
    +關(guān)注

    關(guān)注

    0

    文章

    15

    瀏覽量

    6004
  • UTF-8
    +關(guān)注

    關(guān)注

    0

    文章

    13

    瀏覽量

    7837
  • mybatis
    +關(guān)注

    關(guān)注

    0

    文章

    58

    瀏覽量

    6693

原文標(biāo)題:MyBatis 動(dòng)態(tài) SQL 最全教程,這樣寫 SQL 太爽了!

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Mybatis的特點(diǎn)和核心配置文件

    Mybatis—01基礎(chǔ)&動(dòng)態(tài)SQL
    發(fā)表于 08-07 14:20

    為什么要動(dòng)態(tài)sql語(yǔ)句?

    為什么要動(dòng)態(tài)sql語(yǔ)句?因?yàn)?b class='flag-5'>動(dòng)態(tài)sql語(yǔ)句能夠提供一些比較友好的機(jī)制1、可以使得一些在編譯過(guò)程中無(wú)法獲得完整的sql語(yǔ)句,在程序執(zhí)行階段
    發(fā)表于 12-20 06:00

    jdbc與mybatis的區(qū)別

    MyBatis 是一款優(yōu)秀的持久層框架,它支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集。JDBC是一種用于執(zhí)行SQL
    發(fā)表于 02-02 17:43 ?1.1w次閱讀
    jdbc與<b class='flag-5'>mybatis</b>的區(qū)別

    mybatis是什么_MyBatis的優(yōu)缺點(diǎn)詳解_mybatis框架入門詳解

    Mybatis框架是別人開(kāi)發(fā)的一種半成品軟件,可以用來(lái)通過(guò)定制輔助快速開(kāi)發(fā)是工具。MyBatis應(yīng)用程序根據(jù)XML配置文件創(chuàng)建SqlSessionFactory,SqlSessionFactory在
    發(fā)表于 02-24 09:16 ?2w次閱讀

    mybatis動(dòng)態(tài)sql詳解

    本文詳細(xì)介紹了mybatis執(zhí)行動(dòng)態(tài)sql語(yǔ)句的方法。
    發(fā)表于 02-24 11:37 ?3802次閱讀

    mybatis中#和$的區(qū)別

    ${ } 變量的替換階段是在動(dòng)態(tài) SQL 解析階段,而 #{ }變量的替換是在 DBMS 中。這是 #{} 和 ${} 我們能看到的主要的區(qū)別,除此之外,還有以下區(qū)別:#方式能夠很大程度防止sql
    發(fā)表于 02-24 13:35 ?2223次閱讀

    在使用MyBatisSQL語(yǔ)句優(yōu)化總結(jié)

    MyBatis 作為一款優(yōu)秀的持久層框架,它支持自定義SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。它免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作。還可以通過(guò)簡(jiǎn)單的 XML 或注解來(lái)配置和映射原始
    的頭像 發(fā)表于 02-04 15:20 ?2721次閱讀

    Fluent Mybatis、原生MybatisMybatis Plus對(duì)比

    使用fluent mybatis可以不用寫具體的xml文件,通過(guò)java api可以構(gòu)造出比較復(fù)雜的業(yè)務(wù)sql語(yǔ)句,做到代碼邏輯和sql邏輯的合一。不再需要在Dao中組裝查詢或更新操作,在xml或
    的頭像 發(fā)表于 09-15 15:41 ?1370次閱讀

    MybatisSQL注入審計(jì)的基本方法

    SQL注入漏洞作為WEB安全的最常見(jiàn)的漏洞之一,在java中隨著預(yù)編譯與各種ORM框架的使用,注入問(wèn)題也越來(lái)越少。新手代碼審計(jì)者往往對(duì)Java Web應(yīng)用的多個(gè)框架組合而心生畏懼,不知如何下手,希望通過(guò)Mybatis框架使用不當(dāng)導(dǎo)致的S
    的頭像 發(fā)表于 10-17 11:16 ?1244次閱讀

    一文掌握MyBatis動(dòng)態(tài)SQL使用與原理

    摘要:使用動(dòng)態(tài) SQL 并非一件易事,但借助可用于任何 SQL 映射語(yǔ)句中的強(qiáng)大的動(dòng)態(tài) SQL 語(yǔ)言,M
    的頭像 發(fā)表于 01-06 11:27 ?894次閱讀

    動(dòng)態(tài)Sql介紹

    動(dòng)態(tài)Sql介紹 動(dòng)態(tài) SQLMyBatis 的強(qiáng)大特性之一。如果你使用過(guò) JDBC 或其它類似的框架,你應(yīng)該能理解根據(jù)不同條件拼接
    的頭像 發(fā)表于 05-31 09:34 ?1327次閱讀
    <b class='flag-5'>動(dòng)態(tài)</b><b class='flag-5'>Sql</b>介紹

    什么是SQL注入?Java項(xiàng)目防止SQL注入方式

    Java項(xiàng)目防止SQL注入方式 這里總結(jié)4種: PreparedStatement防止SQL注入 mybatis中#{}防止SQL注入 對(duì)請(qǐng)求參數(shù)的敏感詞匯進(jìn)行過(guò)濾 ngin
    發(fā)表于 10-16 14:26 ?488次閱讀

    mybatis接口動(dòng)態(tài)代理原理

    MyBatis是一款輕量級(jí)的Java持久化框架,它通過(guò)XML或注解配置的方式,將數(shù)據(jù)庫(kù)操作與SQL語(yǔ)句解耦,提供了一種簡(jiǎn)單、靈活的數(shù)據(jù)訪問(wèn)方式。在MyBatis中,使用動(dòng)態(tài)代理技術(shù)來(lái)實(shí)
    的頭像 發(fā)表于 12-03 11:52 ?818次閱讀

    mybatis和mybatisplus的區(qū)別

    個(gè)輕量級(jí)的持久層框架,它提供了一個(gè)靈活的SQL映射機(jī)制,使得開(kāi)發(fā)者可以編寫原生SQL語(yǔ)句來(lái)操作數(shù)據(jù)庫(kù)。MyBatis的設(shè)計(jì)目標(biāo)是將原生SQL和對(duì)象關(guān)系映射(ORM)相結(jié)合,以便開(kāi)發(fā)者可
    的頭像 發(fā)表于 12-03 11:53 ?2374次閱讀

    mybatis中$和井號(hào)區(qū)別

    MyBatis是一個(gè)開(kāi)源的Java持久層框架,它提供了許多強(qiáng)大的功能用于簡(jiǎn)化數(shù)據(jù)庫(kù)操作。在MyBatis中,我們可以使用兩種方式來(lái)動(dòng)態(tài)生成SQL語(yǔ)句:$和#。 和#都可以用來(lái)替換
    的頭像 發(fā)表于 12-03 14:53 ?874次閱讀