文章目錄
- 動態SQL
- if標簽
- trim標簽
- where標簽
- set標簽
- foreach標簽
- include標簽和sql標簽
Mybatis動態SQL的官方文檔: https://mybatis.net.cn/dynamic-sql.html
動態SQL
動態SQL是 MyBatis的強大特性之一,如果是使用JDBC根據不同條件拼接sql很麻煩,例如拼接時要確保不能忘記添加必要的空格,還要注意去掉列表最后一個列名的逗號。利用動態 SQL,可以徹底擺脫這種痛苦。
if標簽
使用場景:在我們數據庫表中字段分為必填字段和非必填字段,對與非必填字段數據庫會自動幫我們賦值,那如果在添加用戶的時候有不確定的字段傳入,程序應該如何實現呢?
這個時候就需要使用動態標簽來判斷了,比如添加的時候性別gender為非必填字段
<insert id="insertUserByCondition">INSERT INTO user_info (username,age,<if test="gender != null">gender,</if>password)VALUES (#{username},#{age},<if test="gender != null">#{gender},</if>#{password})
</insert>
可不可以不進行判斷,直接把字段設置為null呢?
不可以,這種情況下,如果gender字段有默認值,就會設置為默認值
測試代碼
@Testvoid insertUserByCondition() {UserInfo userInfo=new UserInfo();userInfo.setUsername("username5");userInfo.setPassword("password5");userInfo.setGender(5);userInfo.setAge(5);userInfoMapperXML.insertUserByCondition(userInfo);}
不設置gender的參數,也可以進行插入
注意:
- if標簽test中的屬性是傳入對象中的屬性,不是數據庫字段
- 插入語句中,values中賦值也要有if標簽,要一一對應,gender字段中有if標簽,values中也要的gender屬性也要有if標簽
trim標簽
標簽中有如下屬性:
? prefix:表示整個語句塊,以prefix的值作為前綴
? suffix:表示整個語句塊,以suffix的值作為后綴
? prefixOverrides:表示整個語句塊要去除掉的前綴
? suffixOverrides:表示整個語句塊要去除掉的后綴
trim標簽的使用
sql語句
insert into user_info ( username, password, age, gender ) values("username5","password5",5,5)
insert into user_info<trim suffixOverrides="," prefix="(" suffix=")"><if test="username!=null">username,</if><if test="password!=null">password,</if><if test="age!=null">age,</if><if test="gender!=null">gender</if></trim>values (<trim suffixOverrides="," prefix="(" suffix=")"><if test="username!=null">#{username},</if><if test="password!=null">#{password},</if><if test="age!=null">#{age},</if><if test="gender!=null">#{gender}</if></trim>)</insert>
測試代碼
@Testvoid insertUserByCondition() {UserInfo userInfo=new UserInfo();userInfo.setUsername("username5");userInfo.setPassword("password5");userInfo.setGender(5);userInfo.setAge(5);userInfoMapperXML.insertUserByCondition(userInfo);}
where標簽
看下?這個場景,系統會根據我們的篩選條件,動態組裝where條件
這個是怎么實現的呢?通過where標簽
舉個例子
sql語句:
select* from user_info where age=1 and gender =2;
<select id="selectByCondition" resultType="com.example.demo.model.UserInfo">select id, username, age, gender, phone, delete_flag, create_time,update_timefrom user_info where<if test="age != null">age = #{age}</if><if test="gender != null">and gender = #{gender}</if></select>
當if標簽有一個或兩個不符合條件的時候,會報錯,這時候where標簽就派上用場了
<select id="selectByCondition" resultType="com.example.demo.model.UserInfo">select id, username, age, gender, phone, delete_flag, create_time,update_timefrom user_info where<where><if test="age != null">age = #{age}</if><if test="gender != null">and gender = #{gender}</if></where></select>
測試代碼
@Testvoid selectByCondition() {UserInfo userInfo=new UserInfo();userInfo.setAge(16);userInfoMapperXML.selectByCondition(userInfo);}
where標簽只會在子元素有內容的情況下才插入where子句,而且會自動去除子句的開頭的AND或OR
set標簽
sql
update user_info set password="123" ,gender= 4 where id=34
<update id="updateUser2">update user_info set<if test="username!=null">username=#{username}</if><if test="password!=null">,password=#{password}</if><if test="gender!=null">,gender=#{gender}</if>where id=#{id}</update>
如果我們寫出這樣的xml文件,當我們的username為null時,sql語法錯誤,多了一個逗號
下面是報錯信息
set標簽會刪除額外的逗號,并把set插入sql語句中
<update id="updateUser2">update user_info<set><if test="username!=null">username=#{username}</if><if test="password!=null">,password=#{password}</if><if test="gender!=null">,gender=#{gender}</if></set>where id=#{id}</update>
測試代碼
@Testvoid updateUser2() {UserInfo userInfo=new UserInfo();userInfo.setPassword("123");userInfo.setGender(4);```javauserInfo.setId(34);userInfoMapperXML.updateUser2(userInfo);}
foreach標簽
foreach 元素的功能非常強大,它允許你指定一個集合,聲明可以在元素體內使用的集合項(item)和索引(index)變量。它也允許你指定開頭與結尾的字符串以及集在這里插入代碼片
合項迭代之間的分隔符。這個元素也不會錯誤地添加多余的分隔符!
foreach 標簽有如下屬性:
collection:綁定方法參數中的集合,如 List,Set,Map或數組對象
item:遍歷時的每?個對象
open:語句塊開頭的字符串
close:語句塊結束的字符串
separator:每次遍歷之間間隔的字符串
舉個例子:批量查詢id為12,13,14的數據
sql:
select * from user_info where id in ( 12 , 13 ,14)
<select id="selectUserByIds" resultType="com.example.demo.model.UserInfo">select * from user_info where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></select>
測試代碼
@Testvoid selectUserByIds() {List<Integer> ids=new ArrayList<>();ids.add(12);ids.add(13);ids.add(14);userInfoMapperXML.selectUserByIds(ids);}
需求:批量刪除id為12,13,14的數據
<delete id="deleteByIds">delete from user_info where id in<foreach collection="ids" item="id" separator="," open="(" close=")" >#{id}</foreach></delete>
測試代碼
@Testvoid deleteByIds() {List<Integer> ids=List.of(12,13,14);userInfoMapperXML.deleteByIds(ids);}
include標簽和sql標簽
在xml映射文件中配置的SQL,有時可能會存在很多重復的片段,此時就會存在很多冗余的代碼
sql 標簽: 定義可重用的SQL片段
include 標簽:通過屬性refid,指定包含的SQL片段
<sql id="allColumn">id, username, age, gender, phone, delete_flag, create_time, update_time</sql><select id="selectAll" resultType="com.example.demo.model.UserInfo">SELECT<include refid="allColumn"></include>FROM `user_info`</select>
測試代碼
@Testvoid selectAll() {userInfoMapperXML.selectAll().stream().forEach(x-> System.out.println(x));}