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>