在上一篇的:Mybatis 操作數(shù)據(jù)庫的基本 CRUD 以及查詢操作詳析_@糊糊涂涂的博客-CSDN博客中介紹了Mybatis使用固定SQL語句操作數(shù)據(jù),本篇介紹 Mybatis 一個(gè)強(qiáng)大的特性:動(dòng)態(tài)SQL。
動(dòng)態(tài) SQL 解決什么問題?
????????那當(dāng)我們要執(zhí)行的業(yè)務(wù)邏輯有很多,比如給成績(jī)表中插入一行數(shù)據(jù),對(duì)應(yīng)學(xué)生的 “性別” 字段是非必須參數(shù)時(shí),使用動(dòng)態(tài)SQL就不用寫兩種插入語句(傳與不傳性別);
? ? ? ? 另外,當(dāng)執(zhí)行查詢邏輯時(shí),條件中的參數(shù)個(gè)數(shù)也是不確定的。
? ? ? ? 以上類似傳入?yún)?shù)不確定的情況,都可以使用動(dòng)態(tài)SQL來解決。
1. <if> 標(biāo)簽:
?????????<if>標(biāo)簽可以用來判斷參數(shù)是否符合預(yù)期值,從而決定 SQL 語句的拼接;
? ? ? ? 下面假設(shè)要給 student 表插入一行數(shù)據(jù),學(xué)生的 sex 字段對(duì)應(yīng)的實(shí)體類中 sex 屬性值為null,借助<if>標(biāo)簽判斷是否要在插入時(shí)插入 sex :
Maper 接口:?
@Mapper
public interface StudentMapper {
// 新增學(xué)生信息
int addStu(Student student);
}
?插入語句:
<mapper namespace="com.example.demo.mapper.StudentMapper">
<insert id="addStu">
insert into student (uid, name
<if test="sex != null and sex != '' ">
,sex
</if>
,score
) values (#{uid}, #{name}
<if test="sex != null and sex != '' ">
,#{sex}
</if>
,#{score})
</insert>
</mapper>
?測(cè)試方法:
@SpringBootTest
class StudentMapperTest {
@Autowired
private StudentMapper studentMapper;
@Transactional
@Test
void addStu() {
Student student = new Student();
student.setUid(1);
student.setName("張三");
student.setScore(98);
// 傳入的實(shí)體對(duì)象中不包含 sex
int result = studentMapper.addStu(student);
System.out.println("插入成功:" + result);
}
}
?。?!使用時(shí)要注意區(qū)分屬性和字段:
test 里要判斷的是“屬性” —— 來自實(shí)體類對(duì)象;
其他的是字段 —— 和數(shù)據(jù)庫對(duì)應(yīng);
2. <trim> 標(biāo)簽:
? ? ? ? <trim>標(biāo)簽還會(huì)結(jié)合<if>標(biāo)簽一起使用,它有字面意思“修剪”的含義。
? ? ? ? 當(dāng)SQL語句中有很多個(gè)非必傳參數(shù)時(shí),一旦只傳其中個(gè)別參數(shù),就會(huì)導(dǎo)致殘留逗號(hào)或括號(hào)等情況,導(dǎo)致SQL語句出現(xiàn)錯(cuò)誤;<trim> 標(biāo)簽就會(huì)根據(jù)實(shí)際情況,去掉殘留不必要的內(nèi)容。
<trim>標(biāo)簽的四個(gè)參數(shù):
????????可根據(jù)場(chǎng)景添加
- prefix:表示整個(gè)語句塊,以prefix的值作為前綴
- suffix:表示整個(gè)語句塊,以suffix的值作為后綴
- prefixOverrides:表示整個(gè)語句塊要去除掉的前綴
- suffixOverrides:表示整個(gè)語句塊要去除掉的后綴
下面演示:插入一條學(xué)生信息,但參數(shù)只傳學(xué)生名,就會(huì)導(dǎo)致字段后面多出一個(gè)逗號(hào),同時(shí)如果不穿參數(shù),又會(huì)多出一對(duì)括號(hào),借助 trim 來修改:
Mapper 接口:?
@Mapper
public interface StudentMapper {
// 只插入學(xué)生姓名
int addStuOnlyName(Student student);
}
SQL 語句:
<insert id="addStuOnlyName">
insert into student
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="uid != null and uid != '' ">
uid,
</if>
<if test="name != null and name != '' ">
name,
</if>
<if test="sex != null and sex != '' ">
sex,
</if>
<if test="score != null and score != '' ">
score
</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="uid != null and uid != '' ">
#{uid},
</if>
<if test="name != null and name != '' ">
#{name},
</if>
<if test="sex != null and sex != '' ">
#{sex},
</if>
<if test="score != null and score != '' ">
#{score}
</if>
</trim>
</insert>
單元測(cè)試:
@Test
void addStuOnlyName() {
Student student = new Student();
student.setName("李四");
int result = studentMapper.addStuOnlyName(student);
System.out.println("插入成功:" + result);
}
?文章來源地址http://www.zghlxwxcb.cn/news/detail-606725.html
3. <where> 標(biāo)簽:
? ? ? ? 直接借助示例演示:根據(jù)學(xué)生 uid 或 學(xué)生名 來查詢一條學(xué)生信息,這里的兩個(gè)查詢條件都是非必傳的。
? ? ? ? ① 如果查詢時(shí)只給了其中一個(gè)條件,那么 where 后面連接時(shí)的 "and" 就會(huì)被多出來;
? ? ? ? ② 如果兩個(gè)條件都不穿,那么 "where" 就會(huì)被多出來;
針對(duì)第一種情況:可以使用<trim> 標(biāo)簽去后綴的方式去掉 and,and 放在參數(shù)的后面;
針對(duì)第二種情況:解決辦法很多種:
- where 后添加 1=1,and 放在每個(gè)條件參數(shù)前面,使用<trim>去前綴去掉and;
? ? ? ? (但這種寫法很冗余,不是好辦法)
- where 作為<trim>標(biāo)簽的前綴,只有<trim>里有代碼,才會(huì)自動(dòng)加上前綴 where,再按照去后綴的方式去掉 and;
- 使用 <where> 標(biāo)簽,專門解決這種場(chǎng)景:
? ? <where> 里面有內(nèi)容,就會(huì)自動(dòng)生成 where,沒有就不生成。
??????????????? ?同時(shí):如果有多出來的 and ,它也會(huì)按照去前綴的方式去掉
????????
?
4. <set> 標(biāo)簽:
? ? ? ? <set> 標(biāo)簽用于修改場(chǎng)景,<set>標(biāo)簽也是包著所有參數(shù),如果沒有內(nèi)容,就不加 set,但沒有set語句對(duì)于 mysql 是錯(cuò)誤的,所以至少要傳一個(gè)參數(shù)
? ? ? ? <set> 會(huì)自動(dòng)去掉多余的逗號(hào)
<update id="updateStu">
update student
<set>
<if test="uid != null and uid > 0">
uid = #{uid},
</if>
<if test="name != null and name != '' ">
name = #{name},
</if>
<if test="sex != null and sex != '' ">
sex = #{sex},
</if>
<if test="score != null and score > 0">
score = #{score}
</if>
</set>
where uid = #{uid}
</update>
5. <foreach> 標(biāo)簽:
? ? ? ? <foreach> 標(biāo)簽用于遍歷傳入的集合,它有五個(gè)可選項(xiàng):
- collection:綁定方法參數(shù)中的集合,如 List,Set,Map或數(shù)組對(duì)象
- item:遍歷時(shí)的每?個(gè)對(duì)象
- open:語句塊開頭的字符串
- close:語句塊結(jié)束的字符串
- separator:每次遍歷的對(duì)象之間間隔的字符串
// 根據(jù) uid 批量刪除
int deleteByUids(List<Integer> uidList);
<delete id="deleteByUids">
delete from student
where uid in
<foreach collection="uidList" item="uid" open="(" close=")" separator=",">
#{uid}
</foreach>
</delete>
文章來源:http://www.zghlxwxcb.cn/news/detail-606725.html
?
到了這里,關(guān)于借助 Mybatis 的動(dòng)態(tài) SQL 解決傳參不確定問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!