Mybatis批量事務

Mybatis批量事務

mysql數據庫不能同時支持30萬數據的 一次性事務提交,需要分批次地去進行事務的提交,否則數據將堆積到mysql數據庫中,導致數據庫性能過低。(需要採用編程式事務的方式分批次多次提交)

service 層
通過流式表達式實現數據1000條地操作

@Service
@Transactional
public class UserService extends ServiceImpl<UserInfoPojoMapper, UserInfoPojo> implements IUserService {

    @Value(value = "${batchInsertCount}")
    Integer batchInsertCount;

    @Autowired
    SqlSessionFactory sqlSessionFactory;
    //日誌記錄器
    private static Logger logger = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);


    private void insertBatch(List<UserInfoPojo> list) {
        SqlSession sqlSession =sqlSessionFactory.openSession();
        int index = list.size() / batchInsertCount;
        int count = list.size();
        long startTime = System.currentTimeMillis();   //獲取開始時間
        for (int i = 0; i <= index; i++) {
            if (count > 0) {
                try { //每一千條提交一次避免數據堆積
                    //stream流表達式,skip表示跳過前i*10000條記錄,limit表示讀取當前流的前1000條記錄
                    userInfoPojoMapper.BatchInsert(list.stream().skip(i * batchInsertCount).limit(batchInsertCount).collect(Collectors.toList()));
                    sqlSession.commit();
                    long endTime = System.currentTimeMillis(); //獲取結束時間
                    count = count - 1000;
                    logger.info("用戶模塊批量插入-總條數:" + list.size() + ";還剩:" + (count>0?count:0) + "條,已用時:" + (endTime - startTime) + "ms");
                } catch (Exception e) {
                    logger.error("批量插入數據:" + batchInsertCount + "條一次,第" + (i + 1) + "出現異常,進行事務回滾"+e.getMessage(),e);
                    sqlSession.rollback();
                }
            }
        }
    }
    private void updateBatch(List<UserInfoPojo> list) {
        SqlSession sqlSession =sqlSessionFactory.openSession();
        int index = list.size() / batchInsertCount;
        int count = list.size();
        long startTime = System.currentTimeMillis();   //獲取開始時間
        for (int i = 0; i <= index; i++) {
            if (count > 0) {
                try { //每一千條提交一次避免數據堆積
                    //stream流表達式,skip表示跳過前i*10000條記錄,limit表示讀取當前流的前1000條記錄
                    userInfoPojoMapper.BatchUpdate(list.stream().skip(i * batchInsertCount).limit(batchInsertCount).collect(Collectors.toList()));
                    sqlSession.commit();
                    long endTime = System.currentTimeMillis(); //獲取結束時間
                    count = count - 1000;
                    logger.info("用戶模塊批量更新-總條數:" + list.size() + ";還剩:" + (count>0?count:0) + "條,已用時:" + (endTime - startTime) + "ms");
                } catch (Exception e) {
                    logger.error("批量更新數據:" + batchInsertCount + "條一次,第" + (i + 1) + "出現異常,進行事務回滾"+e.getMessage(),e);
                    sqlSession.rollback();
                }
            }
        }
    }

}

****Mapper.xml
useGeneratedKeys=“true” keyProperty=“id” 這裏是爲了實現 insert後將id以set的方式注入到原POJO中
使用#{option.username,jdbcType=VARCHAR}而不是#{option.username} 是爲即使該值即使爲null,也不會報sql錯誤

<!-- 批量導入 -->
<insert id="BatchInsert" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id">
    insert into tb_user (id, username, password,
  usertype, memo, creater,
  create_time, updater, update_time
  )
values
  <foreach collection="list" item="option" index="index" separator=",">
(#{option.id,jdbcType=INTEGER}, #{option.username,jdbcType=VARCHAR}, #{option.password,jdbcType=VARCHAR},
  #{option.usertype,jdbcType=VARCHAR}, #{option.memo,jdbcType=VARCHAR}, #{option.creater,jdbcType=VARCHAR},
  now(), #{option.updater,jdbcType=VARCHAR}, now()
  )
   </foreach>
</insert>


<!-- 批量更新 -->
<update id="BatchUpdate" parameterType="java.util.List">
    <foreach collection="list" item="option" index="index" open="" close="" separator=";">
        update tb_user
        <set>
            password = #{option.password,jdbcType=VARCHAR},
            usertype = #{option.usertype,jdbcType=VARCHAR},
            memo = #{option.memo,jdbcType=VARCHAR},
            creater = #{option.creater,jdbcType=VARCHAR},
            create_time = now(),
            updater = #{option.updater,jdbcType=VARCHAR},
            update_time = now(),
        </set>
        where username = #{option.username,jdbcType=VARCHAR}
    </foreach>
</update>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章