怎樣提高mybatis-plus中saveBatch方法的效率
提高mybatis-plus中saveBatch方法的效率
MyBatis-Plus中的saveBatch方法是一個很方便的批量插入數據的方法,但是如果插入的數據量很大時,可能會出現效率較低的情況。
提高saveBatch方法效率的方法
1.批量插入的數據量不宜過大,否則可能會導致內存溢出。建議根據實際情況選擇合適的批量插入數據的數量。
2.如果插入的數據是從文件或其他數據源中讀取的,可以使用流式插入的方式,將數據流分批插入數據庫,可以減小內存壓力。
3.在執(zhí)行saveBatch方法前,可以通過開啟MyBatis-Plus的批量插入功能,將多條SQL語句合并成一條執(zhí)行,減少與數據庫的交互次數??梢酝ㄟ^以下代碼開啟批
mybatis-plus saveOrUpdateBatch踩坑
mybatis-plus版本: 3.5.1
調用方法
@Transactional(rollbackFor = Exception.class) ?
default boolean saveOrUpdateBatch(Collection<T> entityList) { ?
? ? return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE); ?
}問題說明
當對entityList進行批量更新操作時,方法內部會根據主鍵查詢該記錄,導致批量更新操作十分緩慢,具體代碼如下
@Transactional(rollbackFor = Exception.class)
@Override
public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
? ? TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
? ? Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
? ? String keyProperty = tableInfo.getKeyProperty();
? ? Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
? ? return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> {
? ? ? ? Object idVal = tableInfo.getPropertyValue(entity, keyProperty);
? ? ? ? // 當主鍵存在時,會執(zhí)行sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity)查詢該條記錄
? ? ? ? return StringUtils.checkValNull(idVal) || CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
? ? }, (sqlSession, entity) -> {
? ? ? ? MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
? ? ? ? param.put(Constants.ENTITY, entity);
? ? ? ? sqlSession.update(getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
? ? });
}public static <E> boolean saveOrUpdateBatch(Class<?> entityClass, Class<?> mapper, Log log, Collection<E> list, int batchSize, BiPredicate<SqlSession, E> predicate, BiConsumer<SqlSession, E> consumer) {
?? ?String sqlStatement = getSqlStatement(mapper, SqlMethod.INSERT_ONE);
?? ?return executeBatch(entityClass, log, list, batchSize, (sqlSession, entity) -> {
?? ??? ?// 執(zhí)行predicate
?? ??? ?if (predicate.test(sqlSession, entity)) {
?? ??? ??? ?sqlSession.insert(sqlStatement, entity);
?? ??? ?} else {
?? ??? ??? ?consumer.accept(sqlSession, entity);
?? ??? ?}
?? ?});
}public static <E> boolean executeBatch(Class<?> entityClass, Log log, Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
?? ?Assert.isFalse(batchSize < 1, "batchSize must not be less than one");
?? ?return !CollectionUtils.isEmpty(list) && executeBatch(entityClass, log, sqlSession -> {
?? ??? ?int size = list.size();
?? ??? ?int idxLimit = Math.min(batchSize, size);
?? ??? ?int i = 1;
?? ??? ?for (E element : list) {
?? ??? ??? ?// 循環(huán)每條記錄,執(zhí)行consumer,在此次調用中,consumer中會執(zhí)行predicate,當該條記錄主鍵不為空時,會通過主鍵查詢該記錄
?? ??? ??? ?consumer.accept(sqlSession, element);
?? ??? ??? ?if (i == idxLimit) {
?? ??? ??? ??? ?sqlSession.flushStatements();
?? ??? ??? ??? ?idxLimit = Math.min(idxLimit + batchSize, size);
?? ??? ??? ?}
?? ??? ??? ?i++;
?? ??? ?}
?? ?});
}總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
VS?Code中運行Java?SpringBoot的項目詳細步驟
這篇文章主要介紹了VS?Code中運行Java?SpringBoot項目的相關資料,文中涵蓋了安裝必要的擴展、配置環(huán)境、創(chuàng)建或導入項目、配置調試環(huán)境、運行和調試項目、使用Spring?Boot?Actuator以及配置任務自動化等步驟,需要的朋友可以參考下2024-12-12
JAVA?SSE接口開發(fā)中的Spring?Security與異步線程池配置方法
本文詳細描述了在使用SpringSecurity和異步線程池進行SSE接口開發(fā)時遇到的兩個問題:AccessDeniedException異常和SimpleAsyncTaskExecutor警告,文章還介紹了線程池參數的科學估算方法,并適用于SpringBoot/SpringMVC的SSE接口生產環(huán)境配置,感興趣的朋友一起看看吧2025-12-12

