Mybatis按条件进行批量更新update

本文介绍了一种使用MyBatis进行批量更新的方法,通过Mapper.xml文件中的动态SQL实现根据不同ID更新对应的good_shelves_name字段。该方法适用于需要批量修改数据库中特定记录的场景。

where条件中id值不同,更新的good_shelves_name 字段值也不同
一、Mapper.xml
 
<update id="updateByGoodId" parameterType="com.baiducar.entity.goodsshelves.StorageGoodListDto">

    update base_goods_shelves
    <trim prefix="set" suffixOverrides=",">
        <trim prefix="good_shelves_name =case" suffix="end,">
            <foreach collection="listGoods" item="item" index="index">
                when id=#{item.id} then #{item.goodShelvesName}
            </foreach>
        </trim>
        <trim prefix="is_del =case" suffix="end,">
            <foreach collection="listGoods" item="item" index="index">
                when id=#{item.id} then #{item.isDel}
            </foreach>
        </trim>
    </trim>
    where id in
    <foreach collection="listGoods" index="index" item="item" separator="," open="(" close=")">
        #{item.id,jdbcType=BIGINT}
    </foreach>

</update>

二、接口Mapper.java
/**
 * 根据货架id修改货架名称和isdel
 * @param listDto
 * @return
 */
int updateByGoodId(StorageGoodListDto listDto);
三、传输数据dto,StorageGoodListDto.java 和 GoodsShelves.java
public class StorageGoodListDto implements Serializable {

    private static final long serialVersionUID = 8527410449380915629L;
    /**
     * 仓库id
     */

    private Long storageId;

    /**
     * 仓库编号
     */
    private String deposCode;
    /**
     * 仓库名称
     */
    private String deposName;
    /**
     * 仓库地址
     */

    private String deposAddress;
    /**
     * 仓库管理员
     */
    private String deposManager;

    private List<GoodsShelves> listGoods;

省略set和get方法
}

GoodsShelves.java类:

public class GoodsShelves extends BaseEntity {
    private Long id;

    //仓库id
    private Long baseStorageId;
    //货架名称
    private String goodShelvesName;

省略set和get方法
}


<think> 我们正在讨论MyBatis中如何实现批量更新(尤其是带多条件的情况)。根据用户提供的引用内容,我们可以总结出几种常见的MyBatis批量更新语法,并针对多条件情况进行说明。 ### 1. **MyBatis批量更新的常见方法** 根据引用[1][2][3],MyBatis实现批量更新主要有两种方式: #### (1) **使用`<foreach>`标签拼接多条SQL(推荐)** 这是最常用的方法,通过在update标签内部使用foreach循环生成多条update语句,每条语句更新一行数据。需要数据库连接配置`allowMultiQueries=true`(如MySQL)[^1]。 **语法示例(单条件更新)**: ```xml <update id="updateBatch" parameterType="java.util.List"> <foreach collection="list" item="item" index="index" separator=";"> UPDATE table_name SET column1 = #{item.value1}, column2 = #{item.value2} WHERE id = #{item.id} <!-- 单条件 --> </foreach> </update> ``` #### (2) **使用CASE WHEN实现单条SQL更新多行(适合字段值统一更新)** 这种方法只需要执行一条SQL,但语法复杂,且不适合多条件更新(引用未直接提供,可补充说明): ```sql UPDATE table_name SET column1 = CASE id WHEN #{item1.id} THEN #{item1.value1} WHEN #{item2.id} THEN #{item2.value1} END, column2 = CASE id WHEN #{item1.id} THEN #{item1.value2} WHEN #{item2.id} THEN #{item2.value2} END WHERE id IN (#{item1.id}, #{item2.id}) ``` --- ### 2. **带多条件的批量更新语法** 用户需求是“批量更新且带有多条件”。例如,更新条件不只有主键`id`,可能还包括其他字段(如`status`、`type`等)。下面针对多条件场景提供两种解决方案: #### 方案1:`<foreach>` + 多条件WHERE子句(推荐) 在foreach循环的每条update语句中,WHERE子句包含多个条件: ```xml <update id="updateBatchWithConditions" parameterType="java.util.List"> <foreach collection="list" item="item" separator=";"> UPDATE orders <!-- 示例表名 --> SET status = #{item.status}, amount = #{item.amount} WHERE order_id = #{item.orderId} AND user_id = #{item.userId} <!-- 多条件 --> AND status = 'PENDING' <!-- 固定条件 --> </foreach> </update> ``` **注意事项**: - 数据库连接必须配置`allowMultiQueries=true`(如MySQL)[^1],否则执行会报错。 - 每条update语句独立提交,若中间出错需自行处理事务回滚。 #### 方案2:动态SQL + CASE WHEN(仅适合部分场景) 如果多条件更新需要合并为单条SQL,可使用CASE WHEN,但WHERE条件需覆盖所有可能组合(较复杂): ```sql UPDATE orders SET status = CASE WHEN (order_id = 1001 AND user_id = 2001) THEN 'COMPLETED' WHEN (order_id = 1002 AND user_id = 2002) THEN 'CANCELLED' END, amount = CASE WHEN (order_id = 1001 AND user_id = 2001) THEN 0 WHEN (order_id = 1002 AND user_id = 2002) THEN 10 END WHERE (order_id = 1001 AND user_id = 2001) OR (order_id = 1002 AND user_id = 2002); ``` **MyBatis映射实现**(复杂,不推荐): ```xml <update id="updateBatchMultiCondition"> UPDATE orders SET status = <foreach collection="list" item="item" open="CASE" close="END"> WHEN order_id = #{item.orderId} AND user_id = #{item.userId} THEN #{item.status} </foreach>, amount = <foreach collection="list" item="item" open="CASE" close="END"> WHEN order_id = #{item.orderId} AND user_id = #{item.userId} THEN #{item.amount} </foreach> WHERE <foreach collection="list" item="item" open="" separator="OR" close=""> (order_id = #{item.orderId} AND user_id = #{item.userId}) </foreach> </update> ``` 此方案仅适合小批量数据,否则SQL过长可能引发性能问题。 --- ### 3. **关键配置与事务处理** - **数据库配置**:MySQL需在连接URL中添加`&allowMultiQueries=true`[^1]。 - **事务控制**:在Service层添加`@Transactional`,确保所有update语句在一个事务中执行(任一失败则全部回滚)[^2]。 --- ### 选择建议 - **小批量多条件更新** → **推荐方案1(foreach循环)** ,清晰简单。 - **超大批量更新** → 避免方案2(CASE WHEN),可考虑分批次执行方案1(如每100条执行一次foreach循环)。 > 示例完整代码:引用[3]提供了foreach循环的模板,可在此基础上扩展多条件[^3]。 §§相关问题§§ 1. MyBatis批量更新时如何实现事务回滚? 2. 除了`<foreach>`标签,MyBatis还有哪些批量操作方式? 3. 如何优化MyBatis批量更新的性能? </think> ### MyBatis批量更新多条件语法详解 在MyBatis中实现批量更新(尤其是带多条件)主要通过`<foreach>`标签动态拼接SQL。结合用户提供的引用内容[^1][^2][^3],以下是完整实现方案和注意事项: --- #### 1. **基础语法模板(多字段+多条件)** ```xml <update id="batchUpdate" parameterType="java.util.List"> <foreach collection="list" item="item" separator=";"> UPDATE table_name <set> <!-- 多个更新字段 --> column1 = #{item.field1}, column2 = #{item.field2}, ... </set> WHERE <!-- 多条件 --> condition1 = #{item.cond1} AND condition2 = #{item.cond2} <!-- 支持更多条件 --> </foreach> </update> ``` --- #### 2. **完整实战示例(带详细注释)** 假设需要批量更新`user`表的`status`和`score`字段,条件为`id`和`department`: ```xml <update id="updateUsersBatch" parameterType="java.util.List"> <foreach collection="userList" item="user" separator=";"> UPDATE users <set> status = #{user.newStatus}, score = #{user.newScore} </set> WHERE id = #{user.id} AND department = #{user.dept} AND is_active = 1 <!-- 固定条件 --> </foreach> </update> ``` --- #### 3. **关键配置(解决常见问题)** ##### (1) **数据库连接配置** 必须启用多语句支持(MySQL为例): ```properties # JDBC连接字符串 jdbc:mysql://localhost:3306/db?allowMultiQueries=true ``` > 此配置允许单次执行多个SQL语句(由分号分隔),否则批量更新会报错[^1]。 ##### (2) **Mapper接口定义** Java接口方法需接收List参数: ```java void updateUsersBatch(@Param("userList") List<User> users); ``` --- #### 4. **高级用法:动态条件更新** 若需根据条件跳过某些字段更新(如只更新非空字段): ```xml <foreach collection="list" item="item" separator=";"> UPDATE orders <set> <if test="item.amount != null">amount = #{item.amount},</if> <if test="item.address != null">address = #{item.address},</if> <!-- 动态字段 --> </set> WHERE order_id = #{item.id} AND status = 'PENDING' <!-- 固定条件 --> <if test="item.storeId != null">AND store_id = #{item.storeId}</if> </foreach> ``` --- #### 5. **性能优化建议** 1. **分批次提交** 大数据量时拆分List(如每500条执行一次) ```java for (int i=0; i<list.size(); i+=500) { mapper.batchUpdate(list.subList(i, Math.min(i+500, list.size()))); } ``` 2. **启用批处理** 在SqlSessionFactory配置批量执行器: ```java SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH); ``` --- #### 6. **与其他方案的对比** | 方案 | 优点 | 缺点 | |---------------------|--------------------------|--------------------------| | **`<foreach>`拼接** | 支持多条件、逻辑清晰[^3] | 需配置`allowMultiQueries` | | CASE WHEN | 单条SQL执行 | 条件复杂时难维护 | | 单条循环更新 | 简单直观 | 性能极差(N+1问题)[^2] | > 💡 **推荐**:多条件批量更新首选`<foreach>`方案(引用[^1][^3]已验证) --- ### 典型报错解决方案 - **报错:SQLSyntaxErrorException** 检查数据库是否开启多语句支持(参考章节3.1) - **报错:Parameter not found** 确保`item.属性名`与POJO字段完全匹配 - **性能瓶颈** 采用分批次提交(章节5.1)或启用BATCH执行器
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一路奔跑1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值