Mybatis部分写法总结

MyBatis批量更新与条件更新技巧
本文介绍使用MyBatis实现数据批量更新及条件更新的方法,包括如何在查询时锁定记录并更新字段,以及如何根据ID列表更新数据的类别字段。

一.在获取数据的同时更新某个字段的值

   <select id="getChannelUrl" resultMap="BaseResultMap">
        SELECT * FROM channel_url u ,channel c WHERE u.catgory = #{category}
        AND u.channel_id = c.id
        AND c.status=0
        order by u.down_count
        <if test="count != null and count>=0">
        limit #{count}
        </if>
        for UPDATE;
        UPDATE channel_url u
        , (SELECT u.id FROM channel_url u ,channel c WHERE u.category = #{category}
        AND u.channel_id = c.id
        AND c.status=0
        order by u.down_count
        <if test="count != null and count>=0">
            limit #{count}
        </if>) a SET u.down_count = u.down_count+1 where a.id =u.id;
    </select>

二.更新数据时判断数据值按条件进行更新

    <update id="changeCategyByIds">
        update  channel_url
        set category = (CASE category
        WHEN 0 THEN 1
        WHEN 1 THEN 0
        ELSE 0
        END)
        WHERE id IN
        <foreach collection="list" open="(" separator="," close=")" item="id">
            #{id}
        </foreach>
    </update>
<think>好的,我需要帮用户解决在MyBatis中实现MySQL批量插入存在则更新的写法。用户之前的问题已经涉及到了ON DUPLICATE KEY UPDATE的用法,但现在结合他们提供的引用内容,特别是关于MyBatis配置和批量操作的部分,我需要整合这些信息。 首先,用户提到的引用1、3、4、5都涉及MyBatis的批量操作配置,比如allowMultiQueries参数和foreach循环。引用2提到了使用case when语法进行批量更新,但用户现在需要的是插入时更新,所以可能需要结合ON DUPLICATE KEY UPDATE。 接下来,我要确保回答符合用户的需求,即MyBatis中如何编写批量插入存在则更新的SQL。需要包括XML配置、动态字段处理、事务控制以及可能遇到的问题,比如自增ID跳跃,同时引用提供的资料中的方法。 还要注意用户之前的问题中的回答结构,比如分步骤说明、示例代码、注意事项和常见问题。需要保持一致性,同时补充MyBatis特有的配置和语法,比如allowMultiQueries和foreach标签的使用。 最后,检查是否需要处理多唯一键的情况,或者如何动态生成更新字段,这可能涉及到MyBatis的动态SQL功能,比如使用<if>标签或者OGNL表达式。确保引用正确的参考资料,比如引用1提到的allowMultiQueries配置,引用4中的批量插入示例,以及引用2中的case when方法作为替代方案。 总结步骤:配置数据库连接、编写MyBatis的XML使用ON DUPLICATE KEY UPDATE、处理动态字段、考虑其他方法如case when、注意事项和常见问题。需要结构清晰,示例代码准确,并引用提供的参考资料。</think>### MyBatis中实现MySQL批量插入存在则更新的完整指南 在MyBatis中实现批量插入存在则更新,需结合MySQL的`ON DUPLICATE KEY UPDATE`语法与MyBatis的动态SQL能力。以下是具体实现方法和注意事项: --- #### **1. 配置数据库连接参数** 需在JDBC连接串中添加`allowMultiQueries=true`,否则执行批量SQL时会报错[^1][^3]: ```properties jdbc.url=jdbc:mysql://localhost:3306/db_name?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true ``` --- #### **2. MyBatis XML映射文件写法** 使用`<foreach>`标签拼接批量插入语句,结合`ON DUPLICATE KEY UPDATE`实现存在则更新。 ##### **基础写法** ```xml <insert id="batchInsertOrUpdate"> INSERT INTO user (id, name, age, update_time) VALUES <foreach collection="list" item="item" separator=","> (#{item.id}, #{item.name}, #{item.age}, NOW()) </foreach> ON DUPLICATE KEY UPDATE name = VALUES(name), age = VALUES(age), update_time = NOW() </insert> ``` **说明**: - `VALUES(field)`:引用插入语句中的值 - 表必须包含**唯一索引或主键**(如`id`为主键)[^1][^4] ##### **动态字段更新** 若需根据条件动态更新字段,可使用`<if>`标签: ```xml ON DUPLICATE KEY UPDATE <if test="item.name != null">name = VALUES(name),</if> age = VALUES(age) ``` --- #### **3. 批量操作的Java调用** ```java // Mapper接口定义 public interface UserMapper { void batchInsertOrUpdate(List<User> users); } // 调用示例 List<User> userList = new ArrayList<>(); userList.add(new User(1, "张三", 25)); userList.add(new User(2, "李四", 30)); userMapper.batchInsertOrUpdate(userList); ``` --- #### **4. 替代方案:CASE WHEN批量更新** 若需更复杂的更新逻辑,可结合`<foreach>`生成多条UPDATE语句(需`allowMultiQueries=true`)[^2][^3]: ```xml <update id="batchUpdate"> <foreach collection="list" item="item"> UPDATE user SET name = #{item.name}, age = CASE WHEN #{item.age} > 0 THEN #{item.age} ELSE age END WHERE id = #{item.id}; </foreach> </update> ``` --- #### **5. 性能优化建议** 1. **分批处理**:单次批量操作建议控制在500-1000条以内,避免SQL过长 2. **事务控制**:添加`@Transactional`注解保证原子性 3. **索引优化**:确保唯一索引字段查询效率 ```java @Transactional public void batchProcess(List<User> list) { int batchSize = 500; for (int i = 0; i < list.size(); i += batchSize) { List<User> subList = list.subList(i, Math.min(i + batchSize, list.size())); userMapper.batchInsertOrUpdate(subList); } } ``` --- ### 常见问题解决方案 #### **Q1: 如何避免自增ID不连续?** - 现象:使用`ON DUPLICATE KEY UPDATE`时,冲突记录会导致自增ID跳跃 - 解决方案: ```sql ALTER TABLE user AUTO_INCREMENT = 1; -- 重置自增值 ``` 或调整`innodb_autoinc_lock_mode`参数[^3] #### **Q2: 如何处理多唯一键冲突?** 当表存在多个唯一索引时,任一索引冲突都会触发更新: ```sql CREATE TABLE user ( id INT PRIMARY KEY, email VARCHAR(50) UNIQUE, phone VARCHAR(20) UNIQUE ); ``` 此时插入相同`email`或`phone`都会触发更新 #### **Q3: 如何获取实际插入/更新的记录数?** 通过MyBatis的`@Options`注解获取影响行数: ```java @Options(useGeneratedKeys = false, keyProperty = "id") void batchInsertOrUpdate(List<User> users); ``` 执行后可通过SQL语句`SELECT ROW_COUNT();`获取最后一次操作的影响行数[^4] --- ### 完整示例场景 ##### **表结构** ```sql CREATE TABLE order ( order_id INT AUTO_INCREMENT PRIMARY KEY, order_no VARCHAR(50) UNIQUE, amount DECIMAL(10,2), update_time DATETIME ) ``` ##### **MyBatis映射文件** ```xml <insert id="batchUpsertOrders"> INSERT INTO order (order_no, amount, update_time) VALUES <foreach collection="list" item="item" separator=","> (#{item.orderNo}, #{item.amount}, NOW()) </foreach> ON DUPLICATE KEY UPDATE amount = VALUES(amount), update_time = NOW() </insert> ``` ##### **执行结果** - 当`order_no`存在时:更新金额和更新时间 - 当`order_no`不存在时:插入新订单记录[^4][^5] --- ### 扩展应用技巧 1. **混合插入更新**: ```sql ON DUPLICATE KEY UPDATE status = IF(VALUES(amount) > 1000, 'VIP', status) ``` 2. **保留原值更新**: ```xml ON DUPLICATE KEY UPDATE create_time = create_time -- 保留原始创建时间 ``` 3. **JSON字段更新**: ```sql ON DUPLICATE KEY UPDATE attributes = JSON_SET(attributes, '$.level', VALUES(level)) ``` --- ### 引用说明 1. 数据库连接配置要求[^1][^3] 2. 批量更新替代方案[^2] 3. 自增ID管理策略[^3] 4. 批量操作最佳实践[^4] --- ### 相关问题 1. MyBatis如何实现批量插入时的部分字段更新? 2. 使用`ON DUPLICATE KEY UPDATE`时怎样处理复合唯一键冲突? 3. 如何通过MyBatis拦截器优化批量操作的性能?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值