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();
}

 

最後,技術是服務於業務的,沒有最好的技術,只有相對合適的技術,具體實現根據具體業務選擇。

具體效率數據,後續有時間再單獨測試下再更新文章,各位可根據自身的業務需要結合數據量以及字段數量評估,自行選擇。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章