怎樣提高mybatis-plus中saveBatch方法的效率
提高mybatis-plus中saveBatch方法的效率
MyBatis-Plus中的saveBatch方法是一個很方便的批量插入數(shù)據(jù)的方法,但是如果插入的數(shù)據(jù)量很大時,可能會出現(xiàn)效率較低的情況。
提高saveBatch方法效率的方法
1.批量插入的數(shù)據(jù)量不宜過大,否則可能會導(dǎo)致內(nèi)存溢出。建議根據(jù)實際情況選擇合適的批量插入數(shù)據(jù)的數(shù)量。
2.如果插入的數(shù)據(jù)是從文件或其他數(shù)據(jù)源中讀取的,可以使用流式插入的方式,將數(shù)據(jù)流分批插入數(shù)據(jù)庫,可以減小內(nèi)存壓力。
3.在執(zhí)行saveBatch方法前,可以通過開啟MyBatis-Plus的批量插入功能,將多條SQL語句合并成一條執(zhí)行,減少與數(shù)據(jù)庫的交互次數(shù)。可以通過以下代碼開啟批
mybatis-plus saveOrUpdateBatch踩坑
mybatis-plus版本: 3.5.1
調(diào)用方法
@Transactional(rollbackFor = Exception.class) ? default boolean saveOrUpdateBatch(Collection<T> entityList) { ? ? ? return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE); ? }
問題說明
當對entityList進行批量更新操作時,方法內(nèi)部會根據(jù)主鍵查詢該記錄,導(dǎo)致批量更新操作十分緩慢,具體代碼如下
@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,在此次調(diào)用中,consumer中會執(zhí)行predicate,當該條記錄主鍵不為空時,會通過主鍵查詢該記錄 ?? ??? ??? ?consumer.accept(sqlSession, element); ?? ??? ??? ?if (i == idxLimit) { ?? ??? ??? ??? ?sqlSession.flushStatements(); ?? ??? ??? ??? ?idxLimit = Math.min(idxLimit + batchSize, size); ?? ??? ??? ?} ?? ??? ??? ?i++; ?? ??? ?} ?? ?}); }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot 二維碼生成base64并上傳OSS的實現(xiàn)示例
本文主要介紹了SpringBoot 二維碼生成base64并上傳OSS的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05淺談異常結(jié)構(gòu)圖、編譯期異常和運行期異常的區(qū)別
下面小編就為大家?guī)硪黄獪\談異常結(jié)構(gòu)圖、編譯期異常和運行期異常的區(qū)別。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09