java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > MyBatis CASE WHEN批量更新

MyBatis使用CASE WHEN进行批量更新的高效写法

作者:一勺菠萝丶

当我们使用mybatis的时候,可能经常会碰到一批数据的批量更新问题,因为如果一条数据一更新,那每一条数据就需要涉及到一次数据库的操作,包括网络IO以及磁盘IO,可想而知,这个效率是非常低下的,那么今天我们就来总结一下,如何使用mybatis做批量更新,需要的朋友可以参考下

在实际业务开发中,我们经常需要 批量更新多条数据

最常见的做法是:

for (Item item : list) {
    mapper.update(item);
}

但这样会执行多次 SQL,性能低下,尤其当更新上百条数据时,数据库压力很大。

有没有更高效的方式?

有!可以使用 SQL 的 CASE WHEN 批量更新写法

一、为什么要用 CASE WHEN 批量更新?

传统循环更新的缺点:

CASE WHEN 批量更新的优点:

二、示例场景

假设我们有一张表:

CREATE TABLE erp_product_identity (
  id BIGINT PRIMARY KEY,
  identity_code VARCHAR(50) UNIQUE,
  product_id BIGINT,
  warehouse_id BIGINT,
  update_time DATETIME
);

我们现在有一个 list,需要根据 identity_code 批量更新对应的 product_idwarehouse_id

三、MyBatis 批量更新写法(CASE WHEN)

以下是完整的 MyBatis XML 写法:

<update id="batchUpdateProductIdentityCase">
  UPDATE erp_product_identity
  <set>
    product_id = CASE identity_code
      <foreach collection="list" item="item">
        WHEN #{item.identityCode} THEN #{item.productId}
      </foreach>
    END,
    warehouse_id = CASE identity_code
      <foreach collection="list" item="item">
        WHEN #{item.identityCode} THEN #{item.warehouseId}
      </foreach>
    END,
    update_time = NOW()
  </set>
  WHERE identity_code IN
  <foreach collection="list" item="item" open="(" separator="," close=")">
    #{item.identityCode}
  </foreach>
</update>

四、SQL 生成效果展示

当传入 3 条记录时:

list = [
  { identityCode: 'A001', productId: 11, warehouseId: 101 },
  { identityCode: 'A002', productId: 22, warehouseId: 102 },
  { identityCode: 'A003', productId: 33, warehouseId: 103 }
];

最终生成的 SQL 如下:

UPDATE erp_product_identity
SET
  product_id = CASE identity_code
    WHEN 'A001' THEN 11
    WHEN 'A002' THEN 22
    WHEN 'A003' THEN 33
  END,
  warehouse_id = CASE identity_code
    WHEN 'A001' THEN 101
    WHEN 'A002' THEN 102
    WHEN 'A003' THEN 103
  END,
  update_time = NOW()
WHERE identity_code IN ('A001', 'A002', 'A003');

一次 SQL 更新三条数据。
效率远高于逐条执行!

五、WHERE IN 的作用(非常关键!)

有些人看到这行:

WHERE identity_code IN (...)

可能会问:这不是多余的吗?

其实它是 必须的

没有这个条件,数据库会对整张表执行 UPDATE
未命中的记录的 CASE WHEN 结果是 NULL,导致字段被更新成 NULL,数据直接“报废”。 😱

所以必须加上 WHERE identity_code IN (...) 来限制更新范围。

六、性能对比

更新方式SQL 执行次数性能(1000 条)备注
循环单条更新1000 次🐢 慢每次一条 SQL
MyBatis 批量更新(CASE WHEN)1 次🚀 快一次 SQL 搞定
MyBatis 批量更新(foreach 多值)中等⚡ 一般取决于实现逻辑

推荐场景

当你要批量更新几十到几百条数据(上千条以内)时,CASE WHEN 是最优解。

七、可维护性优化方案

为了可读性更高,可以把 CASE 部分封装成单独 SQL 片段:

<sql id="caseProductId">
  product_id = CASE identity_code
    <foreach collection="list" item="item">
      WHEN #{item.identityCode} THEN #{item.productId}
    </foreach>
  END
</sql>

<sql id="caseWarehouseId">
  warehouse_id = CASE identity_code
    <foreach collection="list" item="item">
      WHEN #{item.identityCode} THEN #{item.warehouseId}
    </foreach>
  END
</sql>

<update id="batchUpdateProductIdentityCase">
  UPDATE erp_product_identity
  <set>
    <include refid="caseProductId"/>
    ,
    <include refid="caseWarehouseId"/>
    ,
    update_time = NOW()
  </set>
  WHERE identity_code IN
  <foreach collection="list" item="item" open="(" separator="," close=")">
    #{item.identityCode}
  </foreach>
</update>

这样结构更清晰、维护更方便。

八、使用建议与限制

项目建议 / 限制
identity_code必须是唯一键或主键
批量数量推荐单次 ≤ 1000 条
SQL 长度MySQL 默认最大 1MB,可通过 max_allowed_packet 调整
时间字段可以统一 update_time = NOW()
数据库适用于 MySQL、PostgreSQL、SQL Server

九、总结

优点缺点
批量更新性能高SQL 长度可能受限
一次执行减少数据库压力可读性稍弱
兼容 MyBatis 动态 SQL仅适合根据主键或唯一字段更新

结语

CASE WHEN 批量更新写法,是 MyBatis 开发中非常实用的一种性能优化技巧。
在日常项目中,当需要 根据不同条件批量更新不同字段值 时,它几乎是最优方案。

 一条 SQL,解决多条更新,让你的系统更快、更稳、更优雅。

以上就是MyBatis使用CASE WHEN进行批量更新的高效写法的详细内容,更多关于MyBatis CASE WHEN批量更新的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文