Mybatis中進(jìn)行批量修改的方法小結(jié)
我們?cè)谑褂?Mybatis 框架進(jìn)行實(shí)現(xiàn)數(shù)據(jù)庫(kù)操作的時(shí)候,通常會(huì)遇到一些需要進(jìn)行批量修改的方式,不同的方式可適用不同的場(chǎng)景,也會(huì)出現(xiàn)一些優(yōu)缺點(diǎn)。本文常見的 Mybatis 批量修改方法并進(jìn)行總結(jié):
1. 循環(huán)修改
通過 Java 循環(huán)調(diào)用單個(gè) update 語(yǔ)句實(shí)現(xiàn)批量修改,不考慮性能,最簡(jiǎn)單,最偷懶的方式。
Mapper 接口:
void updateUser(User user);
XML 映射:
<update id="updateUser">
UPDATE user
SET name = #{name}, age = #{age}
WHERE id = #{id}
</update>
Service中調(diào)用:
for (User user : userList) {
userMapper.updateUser(user);
}
特點(diǎn):
- 實(shí)現(xiàn)簡(jiǎn)單,易于理解和維護(hù)
- 性能差(需要多次進(jìn)行數(shù)據(jù)庫(kù)連接和交互)
- 適用于數(shù)據(jù)量極小的場(chǎng)景
2. 使用 MyBatis 的 foreach 標(biāo)簽構(gòu)建批量修改SQL
通過 foreach 標(biāo)簽動(dòng)態(tài)生成批量更新語(yǔ)句。
Mapper 接口:
void batchUpdate(@Param("list") List<User> userList);
XML 映射:
<update id="batchUpdate">
UPDATE user
SET name = CASE
<foreach collection="list" item="item" index="index">
WHEN id = #{item.id} THEN #{item.name}
</foreach>
END,
age = CASE
<foreach collection="list" item="item" index="index">
WHEN id = #{item.id} THEN #{item.age}
</foreach>
END
WHERE id IN
<foreach collection="list" item="item" separator="," open="(" close=")">
#{item.id}
</foreach>
</update>
特點(diǎn):
- 一次數(shù)據(jù)庫(kù)連接完成批量操作
- SQL 語(yǔ)句長(zhǎng)度隨數(shù)據(jù)量增長(zhǎng),有可能超過數(shù)據(jù)庫(kù)限制
- 適用于中等數(shù)據(jù)量(建議不超過 1000 條)
3. 多條 SQL 語(yǔ)句批量執(zhí)行
在一條 SQL 中包含多個(gè) update 語(yǔ)句,用分號(hào)分隔。 Mapper 接口:
void batchUpdateMultiSQL(@Param("list") List<User> userList);
XML 映射:
<update id="batchUpdateMultiSQL">
<foreach collection="list" item="item" separator=";">
UPDATE user
SET name = #{item.name}, age = #{item.age}
WHERE id = #{item.id}
</foreach>
</update>
注意:進(jìn)行這個(gè)操作的時(shí)候,需要在數(shù)據(jù)庫(kù)連接 URL 中添加 allowMultiQueries=true 參數(shù)(以 MySQL 為例)。
特點(diǎn):
- 實(shí)現(xiàn)簡(jiǎn)單,SQL 語(yǔ)句清晰
- 同樣存在 SQL 長(zhǎng)度限制問題
- 部分?jǐn)?shù)據(jù)庫(kù)可能不支持(需數(shù)據(jù)庫(kù)特性支持)
4. 使用 BatchExecutor(MyBatis 批量執(zhí)行器)
配置 MyBatis 執(zhí)行器為 BATCH 模式,主要作用是累積所有Sql語(yǔ)句進(jìn)行一次性執(zhí)行的操作。
實(shí)現(xiàn)方式:
SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
UserMapper userMapper = session.getMapper(UserMapper.class);
for (User user : userList) {
userMapper.updateUser(user);
}
session.commit();
session.close();
特點(diǎn):
- MyBatis 內(nèi)部?jī)?yōu)化的批量處理方式
- 減少網(wǎng)絡(luò)交互和事務(wù)提交次數(shù)
- 內(nèi)存占用可能較高(需注意批量大?。?/li>
- 適用于大數(shù)據(jù)量批量操作
5. 使用數(shù)據(jù)庫(kù)特定的批量更新語(yǔ)法
某些數(shù)據(jù)庫(kù)提供了專有的批量更新語(yǔ)法,如 PostgreSQL 的 UPDATE ... FROM 語(yǔ)法。
PostgreSQL 示例:
<update id="batchUpdatePostgreSQL">
UPDATE user u
SET name = c.name, age = c.age
FROM (
VALUES
<foreach collection="list" item="item" separator=",">
(#{item.id}, #{item.name}, #{item.age})
</foreach>
) AS c(id, name, age)
WHERE u.id = c.id
</update>
特點(diǎn):
- 性能好,充分利用數(shù)據(jù)庫(kù)特性
- 數(shù)據(jù)庫(kù)兼容性差,移植性低
- 適用于固定使用特定數(shù)據(jù)庫(kù)的場(chǎng)景
方法比較總結(jié)
| 方法 | 優(yōu)點(diǎn) | 缺點(diǎn) | 適用場(chǎng)景 |
|---|---|---|---|
| 循環(huán)修改 | 簡(jiǎn)單直觀,易于調(diào)試 | 性能差,多次交互 | 數(shù)據(jù)量極?。?lt;10 條) |
| foreach 構(gòu)建 CASE 語(yǔ)句 | 一次交互,兼容性好 | SQL 長(zhǎng)度有限制 | 中等數(shù)據(jù)量(<1000 條) |
| 多條 SQL 語(yǔ)句批量執(zhí)行 | 實(shí)現(xiàn)簡(jiǎn)單,SQL 清晰 | 需數(shù)據(jù)庫(kù)支持,有長(zhǎng)度限制 | 數(shù)據(jù)量較小,且數(shù)據(jù)庫(kù)支持 |
| BatchExecutor | 性能好,MyBatis 原生支持 | 內(nèi)存占用高,需手動(dòng)管理會(huì)話 | 大數(shù)據(jù)量批量操作 |
| 數(shù)據(jù)庫(kù)特定語(yǔ)法 | 性能最優(yōu),利用數(shù)據(jù)庫(kù)特性 | 兼容性差,移植性低 | 固定數(shù)據(jù)庫(kù),追求極致性能 |
個(gè)人建議
數(shù)據(jù)量小時(shí)(<100 條),優(yōu)先考慮 foreach 構(gòu)建 CASE 語(yǔ)句。
數(shù)據(jù)量大時(shí)(>1000 條),建議使用 BatchExecutor 并分批處理(每批 500-1000 條)。
考慮數(shù)據(jù)庫(kù)特性,如果項(xiàng)目固定使用某一數(shù)據(jù)庫(kù),可采用其專有的批量語(yǔ)法。
避免循環(huán)單次修改,除非數(shù)據(jù)量極小且對(duì)性能無要求。
最主要一點(diǎn),選擇合適的批量修改方式需綜合考慮數(shù)據(jù)量大小、數(shù)據(jù)庫(kù)類型、性能要求和代碼可維護(hù)性等因素。
到此這篇關(guān)于Mybatis中進(jìn)行批量修改的方法小結(jié)的文章就介紹到這了,更多相關(guān)Mybatis批量修改內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis Interceptor 攔截器的實(shí)現(xiàn)
這篇文章主要介紹了Mybatis Interceptor 攔截器的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12
基于Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單的圖片加載器
這篇文章主要為大家詳細(xì)介紹了如何使用Java?2D?API(Java的繪圖和圖像API)來實(shí)現(xiàn)圖片加載和顯示,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考一下2023-11-11
使用SpringBoot整合高德地圖實(shí)現(xiàn)路線規(guī)劃功能
在日常的開發(fā)項(xiàng)目中,地圖服務(wù)是很多系統(tǒng)的核心能力之一,尤其是在物流、同城配送、出行導(dǎo)航等領(lǐng)域,在近期的一個(gè)項(xiàng)目中,需要實(shí)現(xiàn)用戶下單后,系統(tǒng)需要根據(jù)起點(diǎn)和終點(diǎn)地址,自動(dòng)計(jì)算推薦路徑,所以本文給大家分享了如何使用SpringBoot整合高德地圖實(shí)現(xiàn)路線規(guī)劃功能2025-07-07
Mybatis自關(guān)聯(lián)查詢一對(duì)多查詢的實(shí)現(xiàn)示例
這篇文章主要介紹了Mybatis自關(guān)聯(lián)查詢一對(duì)多查詢的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02
集合框架(Collections Framework)詳解及代碼示例
這篇文章主要介紹了集合框架(Collections Framework)詳解及代碼示例,文章涉及集合數(shù)組的區(qū)別,collection接口,iterator迭代器,list接口及其用法,LinkedHashSet集合等有關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11
深入了解Java8中的時(shí)區(qū)日期時(shí)間
Java?在?java.time?包中也提供了幾個(gè)類用于處理需要關(guān)注時(shí)區(qū)的日期時(shí)間?API,本文將通過簡(jiǎn)單的示例講講它們的用法,需要的可以參考一下2023-04-04
詳解如何使用Java流API構(gòu)建樹形結(jié)構(gòu)數(shù)據(jù)
在實(shí)際開發(fā)中,構(gòu)建樹狀層次結(jié)構(gòu)是常見需求,本文主要為大家詳細(xì)介紹了如何使用Java 8 Stream API將扁平化的菜單數(shù)據(jù)轉(zhuǎn)換為具有層級(jí)關(guān)系的樹形結(jié)構(gòu),需要的可以參考下2024-04-04

