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

mybatis和mybatisplus批量插入問(wèn)題示例詳解

 更新時(shí)間:2023年04月12日 11:51:53   作者:又?欠  
最近在處理一個(gè)功能的時(shí)候,需要批量插入數(shù)據(jù),這篇文章主要給大家介紹了關(guān)于mybatis和mybatisplus批量插入問(wèn)題的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹非常詳細(xì),需要的朋友可以參考下

1. 思路分析:

批量插入是我們?nèi)粘i_(kāi)放經(jīng)常會(huì)使用到的場(chǎng)景,一般情況下我們也會(huì)有兩種方案進(jìn)行實(shí)施,如下所示。

方案一 就是用 for 循環(huán)循環(huán)插入:

優(yōu)點(diǎn):JDBC 中的 PreparedStatement 有預(yù)編譯功能,預(yù)編譯之后會(huì)緩存起來(lái),后面的 SQL 執(zhí)行會(huì)比較快并且JDBC 可以開(kāi)啟批處理,這個(gè)批處理執(zhí)行非常給力。

缺點(diǎn):很多時(shí)候我們的 SQL 服務(wù)器和應(yīng)用服務(wù)器可能并不是同一臺(tái),所以必須要考慮網(wǎng)絡(luò) IO,如果網(wǎng)絡(luò) IO 比較費(fèi)時(shí)間的話,那么可能會(huì)拖慢
SQL 執(zhí)行的速度。

再來(lái)說(shuō)第二種方案,就是生成一條 SQL 插入:

優(yōu)勢(shì):這種方案的優(yōu)勢(shì)在于只有一次網(wǎng)絡(luò) IO,即使分片處理也只是數(shù)次網(wǎng)絡(luò) IO,所以這種方案不會(huì)在網(wǎng)絡(luò) IO 上花費(fèi)太多時(shí)間。

缺點(diǎn)一是 SQL 太長(zhǎng)了,甚至可能需要分片后批量處理;

缺點(diǎn)二是無(wú)法充分發(fā)揮 PreparedStatement 預(yù)編譯的優(yōu)勢(shì),SQL 要重新解析且無(wú)法復(fù)用;三是最終生成的 SQL
太長(zhǎng)了,數(shù)據(jù)庫(kù)管理器解析這么長(zhǎng)的 SQL 也需要時(shí)間。

2. rewriteBatchedStatements=true

在jdbc連接后面加上 rewriteBatchedStatements=true ,加上后才是真正的批量插入。

jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true

3.使用mybatis批量插入:

方案一:使用foreach進(jìn)行插入(生成一條 SQL 插入)

mapper文件

   <insert id="save" parameterType="java.util.List">
        INSERT INTO test
        (
        id,
        a,
        b,
        c
        )
        VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (
            #{item.id},
            #{item.a},
            #{item.b},
            #{item.c}
            )
        </foreach>
    </insert>

調(diào)用方法

 @Override
    public void add() {
        //時(shí)間 一
        long l = System.currentTimeMillis();
        List<TestEntity> list=new ArrayList<>();
        for (int i=0;i<1000;i++){
            TestEntity testEntity=new TestEntity();
            testEntity.setC(i);
            list.add(testEntity);
        }
       testMapper.save(list);
        //時(shí)間 二
        long l1 = System.currentTimeMillis();
        System.out.println("耗時(shí)"+(l1-l));
    }

插入了1000條數(shù)據(jù),耗時(shí)535毫秒。

插入了50000條數(shù)據(jù),直接報(bào)錯(cuò)。

報(bào)錯(cuò)原因是因?yàn)槲覀円粭lSQL進(jìn)行插入導(dǎo)致SQL太長(zhǎng)

解決辦法:

1.修改MySQL配置

2.對(duì)新增數(shù)據(jù)進(jìn)行分片

方案二:一條條插入

mapper

   <insert id="addUserOneByOne" parameterType="com.ruoyi.system.domain.TestEntity">
    insert into test (id,a,b,c) values (#{id},#{a},#,#{c})
    </insert>

測(cè)試代碼

@Service
public class TestServiceimpl extends ServiceImpl<TestMapper, TestEntity> implements TestService {

    @Autowired
  private   TestMapper testMapper;

    @Autowired
  private SqlSessionFactory sqlSessionFactory;
    
    public void addUserOneByOne(List<TestEntity> users) {
        SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
        TestMapper um = session.getMapper(TestMapper.class);
        long startTime = System.currentTimeMillis();
        for (TestEntity user : users) {
            um.addUserOneByOne(user);
        }
        session.commit();
        long endTime = System.currentTimeMillis();
        System.out.println("耗時(shí)"+(endTime - startTime));
    }
}

插入了1000條數(shù)據(jù),耗時(shí)959毫秒。

插入50000條數(shù)據(jù),耗時(shí)11214毫秒。

對(duì)比分析:

如果我們批量插入少部分?jǐn)?shù)據(jù),可以使用方式一,一條SQL進(jìn)行插入。這樣是比較快的。

如果我們插入數(shù)據(jù)達(dá)到,1w條,10來(lái)萬(wàn)條,這時(shí)建議用方式二進(jìn)行插入是比較快的。

4. 使用mybatisplus批量插入

使用saveBatch()方法進(jìn)行批量插入

@Service
public class TestServiceimpl extends ServiceImpl<TestMapper, TestEntity> implements TestService {
    
    @Autowired
  private   TestMapper testMapper;

    @Autowired
  private SqlSessionFactory sqlSessionFactory;

    @Override
    public void add() {
        //時(shí)間 一
        long l = System.currentTimeMillis();
        List<TestEntity> list=new ArrayList<>();
        for (int i=0;i<50000;i++){
            TestEntity testEntity=new TestEntity();
            testEntity.setC(i);
            list.add(testEntity);
        }
        saveBatch(list);
        //時(shí)間 二
        long l1 = System.currentTimeMillis();
        System.out.println("耗時(shí)"+(l1-l));
    }

插入50000條數(shù)據(jù),耗時(shí)19516毫秒

源碼分析

   public boolean saveBatch(Collection<T> entityList, int batchSize) {
        String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE);
        return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {
            sqlSession.insert(sqlStatement, entity);
        });
    }

這里注意 return 中的第三個(gè)參數(shù),是一個(gè) lambda 表達(dá)式,這也是 MP 中批量插入的核心邏輯,可以看到,MP 先對(duì)數(shù)據(jù)進(jìn)行分片(默認(rèn)分片大小是 1000),分片完成之后,也是一條一條的插入。

 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", new Object[0]);
        return !CollectionUtils.isEmpty(list) && executeBatch(entityClass, log, (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();
                }
            }

        });
    }

繼續(xù)查看 executeBatch 方法,就會(huì)發(fā)現(xiàn)這里的 sqlSession 其實(shí)也是一個(gè)批處理的 sqlSession,并非普通的 sqlSession。和我們mybatis使用的方法二一致。

5業(yè)務(wù)場(chǎng)景一對(duì)多怎么處理:

比如,如下這種一對(duì)多場(chǎng)景。

新增的時(shí)候保存都好理解,形成一個(gè)數(shù)組一起保存。

而修改的時(shí)候就有點(diǎn)難處理了,比如我修改了第二條,刪除了第三條,這時(shí)統(tǒng)一保存應(yīng)該怎么處理?

使用 ON DUPLICATE KEY UPDATE (發(fā)生主鍵沖突就更新,沒(méi)有發(fā)生主鍵沖突就新增)

有時(shí)候由于業(yè)務(wù)需求,可能需要先去根據(jù)某一字段值查詢數(shù)據(jù)庫(kù)中是否有記錄,有則更新,沒(méi)有則插入。這個(gè)時(shí)候就可以用到ON DUPLICATE key update這個(gè)sql語(yǔ)句了

mapper如下所示

   <insert id="save" parameterType="java.util.List">
        INSERT INTO test
        (
        id,
        a,
        b,
        c
        )
        VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (
            #{item.id},
            #{item.a},
            #{item.b},
            #{item.c}
            )
        </foreach>
        ON DUPLICATE KEY UPDATE
        id=id,
        a = VALUES(a) ,
        b = VALUES(b),
        c = VALUES(c)
    </insert>

或者在使用mybatisplus時(shí),使用saveOrUpdate()方法進(jìn)行一條數(shù)據(jù)的新增或更新。 saveOrUpdateBatch()方法進(jìn)行批量數(shù)據(jù)的新增或更新。

總結(jié)

到此這篇關(guān)于mybatis和mybatisplus批量插入問(wèn)題的文章就介紹到這了,更多相關(guān)mybatis mybatisplus批量插入問(wèn)題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中使用json與前臺(tái)Ajax數(shù)據(jù)交互的方法

    Java中使用json與前臺(tái)Ajax數(shù)據(jù)交互的方法

    這篇文章主要為大家詳細(xì)介紹了Java中使用json與前臺(tái)Ajax數(shù)據(jù)交互的方法,分享Ajax獲取顯示Json數(shù)據(jù)的一種方法,感興趣的小伙伴們可以參考一下
    2016-06-06
  • 解決spring mvc 多數(shù)據(jù)源切換,不支持事務(wù)控制的問(wèn)題

    解決spring mvc 多數(shù)據(jù)源切換,不支持事務(wù)控制的問(wèn)題

    下面小編就為大家?guī)?lái)一篇解決spring mvc 多數(shù)據(jù)源切換,不支持事務(wù)控制的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • Java多線程面試題(面試官常問(wèn))

    Java多線程面試題(面試官常問(wèn))

    這篇文章主要介紹了Java多線程面試題(面試官常問(wèn)),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • Spring官網(wǎng)下載各版本jar包的方法

    Spring官網(wǎng)下載各版本jar包的方法

    這篇文章主要介紹了Spring官網(wǎng)下載各版本jar包的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-04-04
  • Java并發(fā)編程之Java內(nèi)存模型

    Java并發(fā)編程之Java內(nèi)存模型

    這篇文章主要為大家介紹了Java內(nèi)存模型,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助,希望能夠給你帶來(lái)幫助
    2021-11-11
  • SpringCloud入門實(shí)驗(yàn)環(huán)境搭建

    SpringCloud入門實(shí)驗(yàn)環(huán)境搭建

    這篇文章主要介紹了SpringCloud入門實(shí)驗(yàn)環(huán)境搭建的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用SpringCloud,感興趣的朋友可以了解下
    2021-04-04
  • 詳解Spring如何整合Mybatis

    詳解Spring如何整合Mybatis

    今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著Spring如何整合Mybatis展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • java壓縮文件與刪除文件的示例代碼

    java壓縮文件與刪除文件的示例代碼

    這篇文章主要介紹了java壓縮文件與刪除文件的示例代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • jmeter添加自定義擴(kuò)展函數(shù)之圖片base64編碼示例詳解

    jmeter添加自定義擴(kuò)展函數(shù)之圖片base64編碼示例詳解

    這篇文章主要介紹了jmeter添加自定義擴(kuò)展函數(shù)之圖片base64編碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01
  • 詳解Springboot-MyBatis配置-配置端口號(hào)與服務(wù)路徑(idea社區(qū)版2023.1.4+apache-maven-3.9.3-bin)

    詳解Springboot-MyBatis配置-配置端口號(hào)與服務(wù)路徑(idea社區(qū)版2023.1.4+apache-mav

    這篇文章主要介紹了Springboot-MyBatis配置-配置端口號(hào)與服務(wù)路徑(idea社區(qū)版2023.1.4+apache-maven-3.9.3-bin),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-07-07

最新評(píng)論

昌图县| 中方县| 紫金县| 兖州市| 济源市| 塔城市| 友谊县| 百色市| 陇西县| 开封县| 开远市| 乌兰县| 巩留县| 江川县| 汶川县| 黄平县| 浪卡子县| 丹阳市| 将乐县| 博兴县| 仁化县| 蒲江县| 上思县| 揭阳市| 儋州市| 齐齐哈尔市| 乌拉特中旗| 佛冈县| 虎林市| 那坡县| 曲沃县| 华阴市| 大连市| 澄江县| 乌海市| 拉萨市| 永康市| 云南省| 泰来县| 阆中市| 铜陵市|