Mybatis實(shí)現(xiàn)批量更新數(shù)據(jù)(批量update)
前言
當(dāng)我們使用mybatis的時(shí)候,可能經(jīng)常會(huì)碰到一批數(shù)據(jù)的批量更新問題,因?yàn)槿绻粭l數(shù)據(jù)一更新,那每一條數(shù)據(jù)就需要涉及到一次數(shù)據(jù)庫的操作,包括網(wǎng)絡(luò)IO以及磁盤IO,可想而知,這個(gè)效率是非常低下的。而平時(shí)我們很少直接使用原生jdbc直接操作數(shù)據(jù)庫,而是會(huì)使用比較成熟的ORM框架,那么今天我們就來總結(jié)一下,如何使用mybatis做批量更新。
方案一(個(gè)人推薦)
在mybatis的xml文件中,使用foreach動(dòng)態(tài)標(biāo)簽拼接SQL語句,每一條數(shù)據(jù)的更新語句對(duì)應(yīng)一條update語句,多條語句最終使用";"號(hào)進(jìn)行拼接。
<update id="updateBatchById">
<foreach collection="list" item="item" separator=";">
update
`t_student`
set
`name` = #{item.name},
`age` = #{item.age}
where
id = #{item.id}
</foreach>
</update>測(cè)試執(zhí)行的時(shí)候,通過控制臺(tái)打印,我們可以很方便地看到上述代碼最終生成的SQL語句就是按照我們的本意是由";"號(hào)拼接的語句串。
![]()
這條SQL長串會(huì)一次性發(fā)送給數(shù)據(jù)庫執(zhí)行,只需要進(jìn)行一次網(wǎng)絡(luò)IO,提高了效率。
當(dāng)然,默認(rèn)情況下,數(shù)據(jù)庫是不支持執(zhí)行這樣由";“號(hào)拼接的長串的,執(zhí)行的時(shí)候會(huì)報(bào)錯(cuò),提示說執(zhí)行的SQL有語法錯(cuò)誤

我們需要通過在數(shù)據(jù)庫連接URL中指定allowMultiQueries參數(shù)值為true告訴數(shù)據(jù)庫以支持”;"號(hào)分隔的多條語句的執(zhí)行。
spring.datasource.url=jdbc:mysql://localhost:3306/test?allowMultiQueries=true
方案二(個(gè)人不推薦)
同樣是使用foreach動(dòng)態(tài)標(biāo)簽拼接SQL語句,但是這種方案是最終拼接成一條SQL,而不是多條SQL的長串。
update `t_student`
<trim prefix="set" suffixOverrides=",">
<trim prefix=" `name` = case " suffix=" end, ">
<foreach collection="list" item="item">
<if test="item.name != null">
when `id` = #{item.id} then #{item.name}
</if>
</foreach>
</trim>
<trim prefix=" `age` = case " suffix=" end, ">
<foreach collection="list" item="item">
<if test="item.age != null">
when `id` = #{item.id} then #{item.age}
</if>
</foreach>
</trim>
</trim>
where
`id` in
<foreach collection="list" item="item" open="(" close=")" separator=",">
#{item.id}
</foreach>最終控制臺(tái)打印出的SQL如下
UPDATE `t_student` SET `name` = CASE WHEN `id` = 1 THEN '張三' WHEN `id` = 2 THEN '李四' WHEN `id` = 3 THEN '王五' WHEN `id` = 4 THEN '趙六' END, `age` = CASE WHEN `id` = 1 THEN 40 WHEN `id` = 2 THEN 34 WHEN `id` = 3 THEN 55 WHEN `id` = 4 THEN 76 END WHERE `id` IN ( 1, 2, 3, 4 )
可以發(fā)現(xiàn),如果批量數(shù)據(jù)量太大,要更新的字段太多,那這個(gè)SQL就會(huì)非常難看且復(fù)雜,充斥大量的case when判斷,而且這種case when感覺也會(huì)增大數(shù)據(jù)庫壓力,因?yàn)檫@種case when都需要數(shù)據(jù)庫自己去做判斷,所以個(gè)人感覺不太好,所以不推薦。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java-URLDecoder、URLEncoder使用及說明
本文介紹了Java中URLDecoder和URLEncoder類的使用方法,包括編碼和解碼規(guī)則、推薦的編碼方案、解碼器處理非法字符的方法以及URL編碼和解碼的示例2024-12-12
mybatis單元測(cè)試過程(無需啟動(dòng)容器)
在MyBatis中,單元測(cè)試無需啟動(dòng)容器即可進(jìn)行,主要涉及Configuration類、Executor接口及其實(shí)現(xiàn)類,以及XMLMapperBuilder的作用,Configuration類是配置的承載者,負(fù)責(zé)初始化并解析配置文件,Executor接口及其實(shí)現(xiàn)類2024-09-09
java獲取文件擴(kuò)展名的方法小結(jié)【正則與字符串截取】
這篇文章主要介紹了java獲取文件擴(kuò)展名的方法,結(jié)合實(shí)例形式分析了使用正則與字符串截取兩種獲取擴(kuò)展名的操作技巧,需要的朋友可以參考下2017-01-01
深入淺析SPI機(jī)制在JDK與Spring?Boot中的應(yīng)用
SPI是一種使軟件框架或庫更加模塊化、可擴(kuò)展和可維護(hù)的有效方法。通過遵循“開閉原則”,?SPI?確保了系統(tǒng)的穩(wěn)定性和靈活性,從而滿足了不斷變化的業(yè)務(wù)需求,這篇文章主要介紹了SPI機(jī)制在JDK與Spring?Boot中的應(yīng)用,需要的朋友可以參考下2023-09-09
Java Socket編程(四) 重復(fù)和并發(fā)服務(wù)器
Java Socket編程(四) 重復(fù)和并發(fā)服務(wù)器...2006-12-12
springboot配置log日志按天按類緩存實(shí)現(xiàn)過程
文章介紹了如何配置Spring Boot項(xiàng)目中的`application.yml`文件,并在同級(jí)目錄下創(chuàng)建`logback-spring.xml`文件以自定義日志設(shè)置,最后,展示了運(yùn)行結(jié)果的圖示2026-01-01
Java String字符串補(bǔ)0或空格的實(shí)現(xiàn)代碼
這篇文章主要介紹了Java String字符串補(bǔ)0或空格的實(shí)現(xiàn)代碼,代碼簡單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧2016-09-09
Java中ASCII到十六進(jìn)制的轉(zhuǎn)換指南
在軟件開發(fā)、網(wǎng)絡(luò)通信與底層系統(tǒng)交互中,ASCII 字符與十六進(jìn)制表示之間的轉(zhuǎn)換是一項(xiàng)基礎(chǔ)且高頻的操作,本文將從計(jì)算機(jī)編碼的底層邏輯出發(fā),結(jié)合 Java 平臺(tái)的特性,系統(tǒng)探討 ASCII 轉(zhuǎn)十六進(jìn)制的核心機(jī)制、應(yīng)用場景、設(shè)計(jì)考量與最佳實(shí)踐,需要的朋友可以參考下2026-05-05
SpringMvc靜態(tài)資源訪問實(shí)現(xiàn)方法代碼實(shí)例
這篇文章主要介紹了SpringMvc靜態(tài)資源訪問實(shí)現(xiàn)方法代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08

