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