最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談mybatis-plus批量保存異常及效率優(yōu)化

 更新時(shí)間:2024年01月16日 08:30:40   作者:斗碼士  
本文主要介紹了mybatis-plus批量保存異常及效率優(yōu)化,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

最近基于自己公司內(nèi)部服務(wù)維護(hù),發(fā)現(xiàn)其中調(diào)度中心近期出現(xiàn)不少錯(cuò)誤日志,但是該任務(wù)卻是正常執(zhí)行,生成的報(bào)表數(shù)據(jù)也是正常的,所以很多天沒有發(fā)現(xiàn)問題

這就匪夷所思了,經(jīng)仔細(xì)排查發(fā)現(xiàn),是觸發(fā)了feign超時(shí)hystrix熔斷器機(jī)制

也就是說子服務(wù)出現(xiàn)了執(zhí)行時(shí)間過長的情況

是什么讓它花費(fèi)這么多時(shí)間去執(zhí)行呢,只有一個(gè)for循環(huán),組裝list<object>

這個(gè)組裝過程在java看來是非???,根本不可能出現(xiàn)問題

我發(fā)現(xiàn)了

 iXxxxService.saveBatch(xxxx);

mybatisplus3.3.2自帶的批量保存的sql接口

跟蹤代碼的實(shí)現(xiàn)

在接口發(fā)現(xiàn)IService

   @Transactional(
        rollbackFor = {Exception.class}
    )
    default boolean saveBatch(Collection<T> entityList) {
        return this.saveBatch(entityList, 1000);
    }

    boolean saveBatch(Collection<T> entityList, int batchSize);

ServiceImpl的實(shí)現(xiàn) 

 @Transactional(
        rollbackFor = {Exception.class}
    )
    public boolean saveBatch(Collection<T> entityList, int batchSize) {
        String sqlStatement = this.sqlStatement(SqlMethod.INSERT_ONE);
        return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {
            sqlSession.insert(sqlStatement, entity);
        });
    }
protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
        Assert.isFalse(batchSize < 1, "batchSize must not be less than one", new Object[0]);
        return !CollectionUtils.isEmpty(list) && this.executeBatch((sqlSession) -> {
            int size = list.size();
            int i = 1;

            for(Iterator var6 = list.iterator(); var6.hasNext(); ++i) {
                E element = var6.next();
                consumer.accept(sqlSession, element);
                if (i % batchSize == 0 || i == size) {
                    sqlSession.flushStatements();
                }
            }

        });
    }

可以看到這個(gè)是累計(jì)到一定數(shù)量一起 flush。

很多人認(rèn)為這是mybatisplus設(shè)計(jì)的一個(gè)缺陷,是一條一條去做插入,其實(shí)這是錯(cuò)誤,這種寫法不僅沒錯(cuò)還寫的非常負(fù)責(zé),具體接下來看

方法一

首先要結(jié)合數(shù)據(jù)庫驅(qū)動(dòng)來配合,大家注意這個(gè) rewriteBatchedStatements 玩意,其實(shí)mybatisplus批量保存與這個(gè)的首肯有很大關(guān)系

沒有加它之前

這是沒加之前最好的成績

加了之后最差的成績

可以非常直觀的看出效率明顯提高了好幾倍,所以呢千萬別誤會(huì)mybatisplus這個(gè)設(shè)計(jì),人家完全交給你自主控制,你非得說是它的問題這就不好了

方法二

相比上面方法一的就比較粗暴了

我直接拿過來重寫saveBatch,或者增加一個(gè)特殊的批量保存

第一步

繼承mybatisplus自帶的BaseMapper(這里為什么要繼承我就不說了哈,懂的都懂),添加我們自定義的批量保存方法

zxsSaveBatch

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import java.util.Collection;
public interface BaseMapperPlus <T> extends BaseMapper<T> {

    Integer zxsSaveBatch(Collection<T> entityList);

}

第二步

繼承AbstractMethod,因?yàn)槲覀円膶懰呐坎迦胝Z句,換成我們自己想要實(shí)現(xiàn)的方式

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.util.List;
import java.util.function.Predicate;

@NoArgsConstructor
@AllArgsConstructor
public class ZxsSaveBatch extends AbstractMethod {

    /**
     * 字段篩選條件
     */
    @Setter
    @Accessors(chain = true)
    private Predicate<TableFieldInfo> predicate;

    @SuppressWarnings("Duplicates")
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = new NoKeyGenerator();
        SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
        List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(false) +
            this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY);
        String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET;
        String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(ENTITY_DOT, false) +
            this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY);
        insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET;
        String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA);
        String keyProperty = null;
        String keyColumn = null;
        // 表包含主鍵處理邏輯,如果不包含主鍵當(dāng)普通字段處理
        if (tableInfo.havePK()) {
            if (tableInfo.getIdType() == IdType.AUTO) {
                /* 自增主鍵 */
                keyGenerator = new Jdbc3KeyGenerator();
                keyProperty = tableInfo.getKeyProperty();
                keyColumn = tableInfo.getKeyColumn();
            } else {
                if (null != tableInfo.getKeySequence()) {
                    keyGenerator = TableInfoHelper.genKeyGenerator(getMethod(sqlMethod), tableInfo, builderAssistant);
                    keyProperty = tableInfo.getKeyProperty();
                    keyColumn = tableInfo.getKeyColumn();
                }
            }
        }
        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, getMethod(sqlMethod), sqlSource, keyGenerator, keyProperty, keyColumn);
    }

    @Override
    public String getMethod(SqlMethod sqlMethod) {
        // 自定義 mapper 方法名
        return "zxsSaveBatch";
    }
}

第三步

繼承DefaultSqlInjector,把我們的方法添加進(jìn)去

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;

import java.util.List;

public class ZxsSqlIntorPlus extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);//獲取之前所有的方法
        methodList.add(new ZxsSaveBatch()); //添加自己的方法
        return methodList;
    }

}

第四步

注入到spring

@Bean
    public ZxsSqlIntorPlus zxsSqlIntorPlus() {
        return new ZxsSqlIntorPlus();
    }

第五步

使用方法

之前我們是通過service.saveBatch(Xxxx)來實(shí)現(xiàn)批量插入的

這里我們需要改個(gè)地方,將原本的BaseMapper改成我們新創(chuàng)建的BaseMapperPlus

這是我的例子,當(dāng)然,你也可以是其它的

public interface TestMapper extends BaseMapper<Test> {
}

改為

public interface TestMapper extends BaseMapperPlus<Test> {
}

然后在service里面通過baseMapper.zxsSaveBatch(Xxxx)

當(dāng)然你也可以重寫mybatisplus中IService的批量保存的

測一下速度,發(fā)現(xiàn)不用設(shè)置rewriteBatchedStatements,執(zhí)行速度也更快了,幾乎和rewriteBatchedStatements=true的速度相當(dāng)

到此這篇關(guān)于淺談mybatis-plus批量保存異常及效率優(yōu)化的文章就介紹到這了,更多相關(guān)mybatis-plus批量保存異常內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java 中函數(shù) Function 的使用和定義示例小結(jié)

    Java 中函數(shù) Function 的使用和定義示例小結(jié)

    這篇文章主要介紹了Java 中函數(shù) Function 的使用和定義小結(jié),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • SpringAI?Agent開發(fā)秘籍如何讓javaer也可以用上Agent?Skills

    SpringAI?Agent開發(fā)秘籍如何讓javaer也可以用上Agent?Skills

    文章介紹了如何使用SpringA和Skills構(gòu)建一個(gè)代碼評(píng)審應(yīng)用,通過實(shí)戰(zhàn)示例展示如何利用SpringAI和大模型實(shí)現(xiàn)零配置的代碼評(píng)審功能,感興趣的朋友跟隨小編一起看看吧
    2026-04-04
  • Spring入門到精通之Bean標(biāo)簽詳解

    Spring入門到精通之Bean標(biāo)簽詳解

    這篇文章主要為大家詳細(xì)介紹了Spring中Bean的標(biāo)簽,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Spring有一定的幫助,快跟隨小編一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • SpringBoot集成mybatis連接oracle的圖文教程

    SpringBoot集成mybatis連接oracle的圖文教程

    這篇文章主要介紹了Spring Boot集成mybatis連接oracle的圖文教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 從java源碼分析線程池(池化技術(shù))的實(shí)現(xiàn)原理

    從java源碼分析線程池(池化技術(shù))的實(shí)現(xiàn)原理

    這篇文章主要介紹了從java源碼分析線程池(池化技術(shù))的實(shí)現(xiàn)原理,池化技術(shù)是一種編程技巧,當(dāng)程序出現(xiàn)高并發(fā)時(shí),能夠明顯的優(yōu)化程序,降低系統(tǒng)頻繁創(chuàng)建銷毀連接等額外開銷,下文更多的相關(guān)介紹需要的小伙伴可以參考一下
    2022-04-04
  • 詳解maven中央倉庫連不上的解決辦法

    詳解maven中央倉庫連不上的解決辦法

    這篇文章主要介紹了詳解maven中央倉庫連不上的解決辦法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 淺談BeanPostProcessor加載次序及其對(duì)Bean造成的影響分析

    淺談BeanPostProcessor加載次序及其對(duì)Bean造成的影響分析

    這篇文章主要介紹了淺談BeanPostProcessor加載次序及其對(duì)Bean造成的影響分析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java編程實(shí)現(xiàn)springMVC簡單登錄實(shí)例

    Java編程實(shí)現(xiàn)springMVC簡單登錄實(shí)例

    這篇文章主要介紹了Java編程實(shí)現(xiàn)springMVC簡單登錄實(shí)例,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • springboot整合netty框架實(shí)現(xiàn)站內(nèi)信

    springboot整合netty框架實(shí)現(xiàn)站內(nèi)信

    Netty 是一個(gè)基于NIO的客戶、服務(wù)器端編程框架,使用Netty 可以確保你快速和簡單的開發(fā)出一個(gè)網(wǎng)絡(luò)應(yīng)用,這篇文章主要介紹了springboot整合netty框架的方式小結(jié),需要的朋友可以參考下
    2022-12-12
  • java ThreadPoolExecutor線程池拒絕策略避坑

    java ThreadPoolExecutor線程池拒絕策略避坑

    這篇文章主要為大家介紹了java ThreadPoolExecutor拒絕策略避坑踩坑示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07

最新評(píng)論

台前县| 巫溪县| 收藏| 壤塘县| 虞城县| 环江| 新龙县| 潮安县| 工布江达县| 大宁县| 乳山市| 屏南县| 保山市| 新乡县| 溆浦县| 平遥县| 博湖县| 吉隆县| 和田市| 青岛市| 忻州市| 靖安县| 定南县| 邵武市| 宜兰县| 荥阳市| 通榆县| 西昌市| 深水埗区| 遂宁市| 壶关县| 太康县| 隆安县| 密云县| 宝清县| 揭东县| 大荔县| 宜宾县| 永清县| 安徽省| 方山县|