Mybatis批量更新對(duì)象數(shù)據(jù)的兩種實(shí)現(xiàn)方式
說(shuō)明:
遇到一次需要批量修改對(duì)象的場(chǎng)景。
傳遞一個(gè)對(duì)象集合,需要根據(jù)對(duì)象ID批量修改數(shù)據(jù)庫(kù)數(shù)據(jù),使用的是MyBatis框架。查了一些資料,總結(jié)出兩種實(shí)現(xiàn)方式。
創(chuàng)建Demo
首先,創(chuàng)建一個(gè)簡(jiǎn)單的Demo;
(User,用戶對(duì)象)
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
private String id;
private String username;
private String password;
}(UserController,用戶控制器)
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserMapper userMapper;
/**
* 根據(jù)ID查詢用戶
* @param id
* @return
*/
@GetMapping("/getUser/{id}")
public String getUser(@PathVariable("id") String id){
return userMapper.getUser(id).toString();
}
}(UserMapper,用戶數(shù)據(jù)訪問(wèn)接口)
import com.hezy.pojo.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper {
User getUser(String id);
}數(shù)據(jù)庫(kù)數(shù)據(jù),tb_user表

項(xiàng)目啟動(dòng),測(cè)試一下接口,沒得問(wèn)題;

批量更新
創(chuàng)建一個(gè)新的接口,用于觸發(fā)批量更新對(duì)象的代碼,內(nèi)容是傳遞一個(gè)List集合對(duì)象給Mapper處理;
@GetMapping("/updateUser")
public void updateUser(){
ArrayList<User> users = new ArrayList<>();
User user1 = new User();
user1.setId("1");
user1.setUsername("zhangsan_fix");
User user2 = new User();
user2.setId("2");
user2.setUsername("lisi_fix");
user2.setPassword("654321_fix");
users.add(user1);
users.add(user2);
userMapper.updateUser(users);
}接下來(lái),重點(diǎn)是Mapper.xml中的Statement要怎么寫,繼續(xù)往下看
方式一
首先,我們可以使用動(dòng)態(tài)SQL,如下:
<update id="updateUser">
<foreach collection="users" item="user" separator=";">
update tb_user
<set>
<if test="user.username != null and user.username != ''">
username = #{user.username},
</if>
<if test="user.password != null and user.password != ''">
password = #{user.password}
</if>
</set>
where id = #{user.id}
</foreach>
</update>我們把拼接后的SQL打印出來(lái),會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題。SQL中,分號(hào)(;)表示一條語(yǔ)句的結(jié)束,使用上面的方式拼接出來(lái)的方式,是多條SQL。

因此產(chǎn)生了一個(gè)問(wèn)題,Mybatis中一個(gè)Statement標(biāo)簽中可以有多條SQL嗎?
答案是默認(rèn)不可以,所以上面的代碼報(bào)錯(cuò)了。
需要在數(shù)據(jù)庫(kù)連接后面加上&allowMultiQueries=true配置,如下:

再次執(zhí)行,修改成功了,這是第一種方式;


查看日志發(fā)現(xiàn),Updates:1,就是說(shuō)如果需要返回更新的記錄條數(shù),那么這種方式返回的更新條數(shù)會(huì)是1,不能體現(xiàn)出數(shù)據(jù)庫(kù)真實(shí)發(fā)生變化的記錄條數(shù);
另外,將多條SQL合成一條執(zhí)行,有SQL注入的風(fēng)險(xiǎn)
方式二
第二種方式是用一條SQL的方式來(lái)實(shí)現(xiàn),如下:
<update id="updateUser">
update tb_user
set
username = case
<foreach collection="users" item="user">
when id = #{user.id}
<choose>
<when test="user.username != null and user.username != ''">then #{user.username}</when>
<otherwise>then username</otherwise>
</choose>
</foreach>
end,
password = case
<foreach collection="users" item="user">
when id = #{user.id}
<choose>
<when test="user.password != null and user.password != ''">then #{user.password}</when>
<otherwise>then password</otherwise>
</choose>
</foreach>
end
where
<foreach collection="users" item="user" separator="or">
id = #{user.id}
</foreach>
</update>看著有些復(fù)雜,拼接后的SQL如下:
update tb_user set username = case when id = '1' then 'zhangsan_fix' when id = '2' then 'lisi_fix' end, password = case when id = '1' then password when id = '2' then '654321_fix' end where id = '1' or id = '2';
這種方式不需要加額外的配置,執(zhí)行測(cè)試;

查看數(shù)據(jù)庫(kù),沒得問(wèn)題,批量修改完成了;

總結(jié)
本文介紹了Mybatis框架下,批量更新對(duì)象的兩種方法:
- 方法一:將多條更新語(yǔ)句合成一條執(zhí)行,需要在數(shù)據(jù)庫(kù)鏈接后面增加配置,不能體現(xiàn)真實(shí)修改的記錄條數(shù),有SQL注入的風(fēng)險(xiǎn);
- 方法二:使用case then 關(guān)鍵字實(shí)現(xiàn),SQL復(fù)雜,行數(shù)多,降低了可閱讀性;
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java多態(tài)和實(shí)現(xiàn)接口的類的對(duì)象賦值給接口引用的方法(推薦)
下面小編就為大家?guī)?lái)一篇Java多態(tài)和實(shí)現(xiàn)接口的類的對(duì)象賦值給接口引用的方法(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
Mybatis-plus+通用mapper(tk.mybatis)的使用
本文主要介紹了Mybatis-plus+通用mapper(tk.mybatis)的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧<BR>2024-03-03
Java使用跳轉(zhuǎn)結(jié)構(gòu)實(shí)現(xiàn)隊(duì)列和棧流程詳解
這篇文章主要介紹了Java使用跳轉(zhuǎn)結(jié)構(gòu)實(shí)現(xiàn)隊(duì)列和棧流程,連續(xù)結(jié)構(gòu)和跳轉(zhuǎn)結(jié)構(gòu)是數(shù)據(jù)結(jié)構(gòu)中常見的兩種基本數(shù)據(jù)結(jié)構(gòu),而我們本次的主角棧和隊(duì)列都 既可以使用使用跳轉(zhuǎn)結(jié)構(gòu)實(shí)現(xiàn)也可以使用連續(xù)結(jié)構(gòu)實(shí)現(xiàn)2023-04-04
Spring Cloud下OAUTH2注銷的實(shí)現(xiàn)示例
本篇文章主要介紹了Spring Cloud下OAUTH2注銷的實(shí)現(xiàn)示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03

