MyBatis批量update更新

最近业务需要同步远程数据,而远程数据只开放HTTP接口,返回JSON,用ETL工具比较难做,还是决定写个简单程序。看到好多文章写到批量更新时提到如下格式会报错

<update id="updateBatch" parameterType="java.util.List">
  <foreach item="item" collection="list" separator=";" index="index">
    update myTable set name=#{item.name}
    where id = #{id}
  </foreach>
</update>

建议使用以下格式:

<update id="updateBatch" parameterType="java.util.List">
  update table set index=
  <foreach collection="list" item="item" index="index" separator=" " open="case ID" close="end">
    when #{item.id} then #{item.name}
  </foreach>
  where ID in
  <foreach collection="list" item="item" index="index" separator="," open="(" close=")">
    #{item.id}
  </foreach>
</update>

 其实第一种格式是可以的,只要在配置数据库连接地址中加上&allowMultiQueries=true就可以

jdbcDriver=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql:///localhost:3306/test?characterEncoding=utf-8&allowMultiQueries=true
jdbcusername=root
jdbcpassword=root

1、第一种格式书写方便,看起来更直观,但是生成的sql依然是一条数据一条。和代码for循环差别不大,数据量特别大的时候效率特别低。

2、第二种只生成一条sql,但是sql写起来相当麻烦,每个字段要一个foreach,字段特别多的时候遍历效率也不高,并且如果百万级的数据一条sql推送到db,db压力特别大,锁表时间也特别长。

 

其实mybatis还有一种方式,通过可以批量提交的 SqlSession 执行:

@Autowired
private SqlSessionFactory sqlSessionFactory;
 
@Transactional(rollbackFor = Exception.class)
@Override
public void batchTest() {
    int commitSize = 200;//单次提交数量
    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
    PersonMapper mapper = sqlSession.getMapper(PersonMapper.class);
    List<Person> personList = mapper.selectAll();
    for (int i = 0; i < personList.size(); i++) {
        Person person = personList.get(i);
        person.setName(person.getName() + "Test");
        mapper.updateById(person);
        //达到数量提交一次
        if((i + 1) % commitSize == 0){
            sqlSession.flushStatements();
        }
    }
    sqlSession.flushStatements();
}

 

最后,技术是服务于业务的,没有最好的技术,只有相对合适的技术,具体实现根据具体业务选择。

具体效率数据,后续有时间再单独测试下再更新文章,各位可根据自身的业务需要结合数据量以及字段数量评估,自行选择。

 

### 使用 MyBatis 进行批量更新 MyBatis 支持多种方式来执行批量更新操作,这有助于优化数据库交互并减少应用程序与数据库之间的数据传输量[^1]。 #### 方法一:使用 `foreach` 标签实现批量更新 通过 XML 映射文件中的 `<update>` 和 `<foreach>` 标签组合可以轻松完成批量更新。这种方式允许开发者自定义 SQL 语句,并能有效地处理多个记录的同时更新。 ```xml <update id="batchUpdateUsers" parameterType="java.util.List"> UPDATE users SET name=#{item.name}, email=#{item.email} WHERE user_id=#{item.userId} <foreach collection="list" item="item" separator=";"> <!-- Each iteration will generate an individual update statement --> </foreach> </update> ``` 此方法利用分号(`;`)作为每条独立更新命令间的分隔符,在某些情况下可能需要调整 JDBC 驱动程序设置以支持多条语句的执行。 #### 方法二:启用批处理模式 为了进一步提高性能,可以在会话级别开启批处理功能。当启用了批处理之后,所有的插入、更新以及删除操作都会被缓存起来直到调用 `flushStatements()` 或者关闭 session 的时候才会真正提交给数据库服务器。 ```java try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) { UserMapper mapper = sqlSession.getMapper(UserMapper.class); for (User user : userList) { mapper.updateUser(user); // This won't be sent immediately but cached instead. } sqlSession.flushStatements(); // Send all updates at once after processing entire list. } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } ``` 这种方法不仅提高了效率还减少了网络往返次数,对于大规模的数据集尤其有效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值