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

Mybatis實(shí)現(xiàn)批量操作8種小結(jié)

 更新時(shí)間:2024年10月27日 16:01:53   作者:程序員小強(qiáng)  
本文對(duì)Mybatis的五種批處理方式進(jìn)行了性能測(cè)試,包括批量新增和批量修改,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

批量新增

1.方式一(常用)

<!-- 批量新增-->
<insert id="batchSave" parameterType="java.util.List">
    INSERT INTO lp_user_test_batch
    (
    id,
    user_id,
    user_name,
    user_age,
    type,
    create_time,
    update_time
    )
    VALUES
    <foreach collection="list" item="item" index="index" separator=",">
        (
        #{item.id,jdbcType=BIGINT},
        #{item.userId,jdbcType=VARCHAR},
        #{item.userName,jdbcType=VARCHAR},
        #{item.userAge,jdbcType=INTEGER},
        #{item.type,jdbcType=INTEGER},
        #{item.createTime,jdbcType=TIMESTAMP},
        #{item.updateTime,jdbcType=TIMESTAMP}
        )
    </foreach>
</insert>

測(cè)試結(jié)果

數(shù)量耗時(shí)
10001469ms
20002534ms
30002613ms
40003549ms
50004733ms
80005761ms
100006055ms

2.方式二

批量新增或更新方式
注:需要給唯一主鍵添加唯一索引,update才會(huì)生效

<!-- 批量新增或更新-->
<insert id="batchSaveOrUpdate" parameterType="java.util.List">
    INSERT INTO lp_user_test_batch
    (
    id,
    user_id,
    user_name,
    user_age,
    type,
    create_time,
    update_time
    )
    VALUES
    <foreach collection="list" item="item" index="index" separator=",">
        (
        #{item.id,jdbcType=BIGINT},
        #{item.userId,jdbcType=VARCHAR},
        #{item.userName,jdbcType=VARCHAR},
        #{item.userAge,jdbcType=INTEGER},
        #{item.type,jdbcType=INTEGER},
        #{item.createTime,jdbcType=TIMESTAMP},
        #{item.updateTime,jdbcType=TIMESTAMP}
        )
    </foreach>
    ON DUPLICATE KEY UPDATE
    user_name = VALUES(user_name),
    user_age = VALUES(user_age),
    type = VALUES(type),
    update_time = VALUES(update_time)
</insert>

測(cè)試結(jié)果

數(shù)量耗時(shí)
10001692ms
20002346ms
30003249ms
40003443ms
50003999ms
80006460ms
100007053ms

3.方式三

單條sql+批量方式的SqlSession

<insert id="insert" >
    INSERT INTO lp_user_test_batch
    (
    id,
    user_id,
    user_name,
    user_age,
    type,
    create_time,
    update_time
    )
    values
    (
    #{id,jdbcType=BIGINT},
    #{userId,jdbcType=VARCHAR},
    #{userName,jdbcType=VARCHAR},
    #{userAge,jdbcType=INTEGER},
    #{type,jdbcType=INTEGER},
    #{createTime,jdbcType=TIMESTAMP},
    #{updateTime,jdbcType=TIMESTAMP}
    )
</insert>
@Resource(name = "sqlSessionFactory")
private SqlSessionFactory sqlSessionFactory;

/**
 * 利用 MyBatis 批處理特性,批量提交
 */
public void batchInsert(List<UserTestBatchDO> testBatchDAOList) {
    //集合非空
    if (CollectionUtils.isEmpty(testBatchDAOList)) {
        return;
    }
    //批處理方式 SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
    //獲得對(duì)應(yīng)的Mapper
    UserTestBatchDOMapper userTestBatchDOMapper = sqlSession.getMapper(UserTestBatchDOMapper.class);
    try {
        for (UserTestBatchDO testBatchDO : testBatchDAOList) {
            userTestBatchDOMapper.insert(testBatchDO);
        }
        //統(tǒng)一提交
        sqlSession.commit();
    } catch (Exception e) {
        //沒(méi)有提交的數(shù)據(jù)可以回滾
        sqlSession.rollback();
    } finally {
        //關(guān)閉 sqlSession
        sqlSession.close();
    }
}

測(cè)試結(jié)果

數(shù)量耗時(shí)
10002174ms
20003104ms
30003801ms
40004991ms
50005930ms
80008151ms
100008252ms

批量修改

1.方式一

批量新增或更新方式
注:需要給唯一主鍵添加唯一索引,update才會(huì)生效

<!-- 批量新增或更新-->
<insert id="batchSaveOrUpdate" parameterType="java.util.List">
    INSERT INTO lp_user_test_batch
    (
    id,
    user_id,
    user_name,
    user_age,
    type,
    create_time,
    update_time
    )
    VALUES
    <foreach collection="list" item="item" index="index" separator=",">
        (
        #{item.id,jdbcType=BIGINT},
        #{item.userId,jdbcType=VARCHAR},
        #{item.userName,jdbcType=VARCHAR},
        #{item.userAge,jdbcType=INTEGER},
        #{item.type,jdbcType=INTEGER},
        #{item.createTime,jdbcType=TIMESTAMP},
        #{item.updateTime,jdbcType=TIMESTAMP}
        )
    </foreach>
    ON DUPLICATE KEY UPDATE
    user_name = VALUES(user_name),
    user_age = VALUES(user_age),
    type = VALUES(type),
    update_time = VALUES(update_time)
</insert>

測(cè)試結(jié)果
注:當(dāng)前表內(nèi)數(shù)據(jù)行數(shù) 10000

數(shù)量耗時(shí)
10001505ms
20002617ms
30002922ms
40003292ms
50003443ms
80004832ms
100004886ms

優(yōu)點(diǎn):速度快
缺點(diǎn):使用特殊語(yǔ)法 on duplicate key update 語(yǔ)法 增加sql難度性

2.方式二

單條sql+批量方式的SqlSession

<update id="updateByUserId" >
    UPDATE  lp_user_test_batch
    SET
    user_name = #{userName,jdbcType=VARCHAR},
    user_age = #{userAge,jdbcType=INTEGER},
    type = #{type,jdbcType=INTEGER},
    update_time = #{updateTime,jdbcType=TIMESTAMP}
    WHERE user_id = #{userId,jdbcType=VARCHAR}
</update>

@Resource(name = "sqlSessionFactory")
private SqlSessionFactory sqlSessionFactory;

/**
 * 利用 MyBatis 批處理特性,批量更新
 */
public void batchUpdate(List<UserTestBatchDO> testBatchDAOList) {
    //集合非空
    if (CollectionUtils.isEmpty(testBatchDAOList)) {
        return;
    }
    //批處理方式 SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
    //獲得對(duì)應(yīng)的Mapper
    UserTestBatchDOMapper userTestBatchDOMapper = sqlSession.getMapper(UserTestBatchDOMapper.class);
    try {
        for (UserTestBatchDO testBatchDO : testBatchDAOList) {
            userTestBatchDOMapper.updateByUserId(testBatchDO);
        }
        //統(tǒng)一提交
        sqlSession.commit();
        //清理緩存,防止溢出
        sqlSession.clearCache();
    } catch (Exception e) {
        //沒(méi)有提交的數(shù)據(jù)可以回滾
        sqlSession.rollback();
    } finally {
        //關(guān)閉 sqlSession
        sqlSession.close();
    }
}

測(cè)試結(jié)果
注:當(dāng)前表內(nèi)數(shù)據(jù)行數(shù) 10000

數(shù)量耗時(shí)
10003158ms
20004324ms
30006466ms
40007572ms
50009812ms
800012846ms
1000016088ms

優(yōu)點(diǎn):通過(guò)日志觀察,生成一條執(zhí)行語(yǔ)句sql ,多行參數(shù),統(tǒng)一commit
缺點(diǎn):比方式一速度略慢

3.方式三

java程序循環(huán)調(diào)用單條修改語(yǔ)句
執(zhí)行方式:一條sql ,程序循環(huán)執(zhí)行

for (UserTestBatchDO userTestBatch : testBatchDAOList) {
    userTestBatchDOMapper.updateByUserId(userTestBatch);
}

測(cè)試結(jié)果
注:當(dāng)前表內(nèi)數(shù)據(jù)行數(shù) 10000

數(shù)量耗時(shí)
100033907ms
200042866ms
300089675ms
5000?104833ms

優(yōu)點(diǎn):方便單條控制提交事物
缺點(diǎn):耗時(shí),耗性能、每一次循環(huán)都需要與數(shù)據(jù)庫(kù)交互一次

4.方式四

Mybatis foreach 循環(huán)
執(zhí)行方式:拼接好一條sql,后執(zhí)行

<!-- 接收l(shuí)ist參數(shù),循環(huán)著組裝sql語(yǔ)句,注意for循環(huán)的寫(xiě)法
             separator=";" 代表著每次循環(huán)完,在sql后面放一個(gè)分號(hào) -->
<update id="updateForeachByUserId" parameterType="java.util.List">
    <foreach collection="list" item="item" separator=";">
        UPDATE lp_user_test_batch
        SET
        user_name = #{item.userName,jdbcType=VARCHAR},
        user_age = #{item.userAge,jdbcType=INTEGER},
        type = #{item.type,jdbcType=INTEGER},
        update_time = #{item.updateTime,jdbcType=TIMESTAMP}
        WHERE user_id = #{item.userId,jdbcType=VARCHAR}
    </foreach>
</update>

測(cè)試結(jié)果
注:當(dāng)前表內(nèi)數(shù)據(jù)行數(shù) 10000

數(shù)量耗時(shí)
10002671ms
2000?4170ms
30004514ms
40005152ms
5000?6572ms
800010209ms
1000012158ms

優(yōu)點(diǎn):生成多條sql,統(tǒng)一執(zhí)行,與數(shù)據(jù)庫(kù)交互次數(shù)少
缺點(diǎn) : 生成多條拼接的update語(yǔ)句,update語(yǔ)句比較多,量大了就有可能造成sql阻塞。

5.方式五

mybatis sql 使用 case when

<!-- 批量更新第二種方法,通過(guò) case when語(yǔ)句變相的進(jìn)行批量更新 -->
    <update id="updateCaseByUserId" parameterType="java.util.List">
        update lp_user_test_batch
        <trim prefix="set" suffixOverrides=",">

            <!-- 拼接case when 這是另一種寫(xiě)法 -->
            <trim prefix="user_name =case" suffix="end,">
                <foreach collection="list" item="item">
                    <if test="item.userName!=null">
                        when user_id = #{item.userId,jdbcType=VARCHAR} then #{item.userName,jdbcType=VARCHAR}
                    </if>
                </foreach>
            </trim>

            <trim prefix="user_age =case" suffix="end,">
                <foreach collection="list" item="item">
                    <if test="item.userAge!=null">
                        when user_id = #{item.userId,jdbcType=VARCHAR} then #{item.userAge,jdbcType=INTEGER}
                    </if>
                </foreach>
            </trim>

            <trim prefix="type =case" suffix="end,">
                <foreach collection="list" item="item">
                    <if test="item.type!=null">
                        when user_id = #{item.userId,jdbcType=VARCHAR} then #{item.type,jdbcType=INTEGER}
                    </if>
                </foreach>
            </trim>

            <trim prefix="update_time =case" suffix="end,">
                <foreach collection="list" item="item">
                    <if test="item.type!=null">
                        when user_id = #{item.userId,jdbcType=VARCHAR} then #{item.updateTime,jdbcType=TIMESTAMP}
                    </if>
                </foreach>
            </trim>
        </trim>
         <where>
            user_id in
            <foreach collection="list" index="index" item="item" separator="," open="(" close=")">
                #{item.userId,jdbcType=VARCHAR}
            </foreach>
        </where>
    </update>

測(cè)試結(jié)果
注:當(dāng)前表內(nèi)數(shù)據(jù)行數(shù) 10000

數(shù)量耗時(shí)
10003201ms
20004804ms
30006833ms
40008554ms
500011688ms
800026501ms
1000034724ms

缺點(diǎn):
xml中的循環(huán)體有點(diǎn)多,每一個(gè)case when 都要循環(huán)一遍list集合,所以大批量拼sql的時(shí)候會(huì)比較慢。
生成多條拼接sql,sql長(zhǎng)度過(guò)長(zhǎng),容易sql超長(zhǎng)引起報(bào)錯(cuò) Packet for query is too large。

MySQL 最大允許的 packet

在這里插入圖片描述

Mybatis批處理介紹

Mybatis內(nèi)置執(zhí)行器類(lèi)型ExecutorType有3種
分別是
ExecutorType.SIMPLE: 不做特殊處理,為每個(gè)語(yǔ)句的執(zhí)行創(chuàng)建一個(gè)新的預(yù)處理語(yǔ)句。
ExecutorType.REUSE: 可以復(fù)用預(yù)處理語(yǔ)句。
ExecutorType.BATCH:可以批量執(zhí)行所有更新語(yǔ)句

SIMPLE與BATCH(批量)對(duì)比默認(rèn)的是simple,該模式下它為每個(gè)語(yǔ)句的執(zhí)行創(chuàng)建一個(gè)新的預(yù)處理語(yǔ)句,單條提交sql;
而batch模式重復(fù)使用已經(jīng)預(yù)處理的語(yǔ)句,并且批量執(zhí)行所有更新語(yǔ)句,顯然batch性能將更優(yōu);但是批量模式無(wú)法返回自增主鍵

測(cè)試環(huán)境配置

系統(tǒng):win 8.1
Mysql : 5.7
java環(huán)境:junit
注:環(huán)境不同可能會(huì)引起耗時(shí)存在差異。

總結(jié)

單次批量操作不要過(guò)大,批量新增使用方式一,批量更新方式一與方式二經(jīng)過(guò)測(cè)試是最優(yōu)的選擇
也可以根據(jù)安全方面綜合考慮,選擇適合的方式。

到此這篇關(guān)于Mybatis實(shí)現(xiàn)批量操作8種小結(jié)的文章就介紹到這了,更多相關(guān)Mybatis 批量操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot前后端分離實(shí)現(xiàn)個(gè)人博客系統(tǒng)

    SpringBoot前后端分離實(shí)現(xiàn)個(gè)人博客系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了使用springboot+mybatis+前端vue,使用前后端分離架構(gòu)實(shí)現(xiàn)的個(gè)人博客系統(tǒng),感興趣的小伙伴可以動(dòng)手嘗試一下
    2022-06-06
  • MyBatis-Plus中提供的各種注解詳細(xì)說(shuō)明

    MyBatis-Plus中提供的各種注解詳細(xì)說(shuō)明

    這篇文章主要介紹了MyBatis-Plus中提供的各種注解詳細(xì)說(shuō)明,下面對(duì)MyBatis-Plus提供的注解進(jìn)行整理,本文提供了部分示例代碼以方便理解,需要的朋友可以參考下
    2023-11-11
  • Mybatis框架及原理實(shí)例分析

    Mybatis框架及原理實(shí)例分析

    這篇文章主要介紹了Mybatis框架及原理實(shí)例分析,需要的朋友可以參考下
    2017-08-08
  • SpringBoot整合Mybatis-plus的具體使用

    SpringBoot整合Mybatis-plus的具體使用

    本文主要介紹了SpringBoot整合Mybatis-plus的具體使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Jackson3遷移核心注意點(diǎn)總結(jié)大全

    Jackson3遷移核心注意點(diǎn)總結(jié)大全

    在升級(jí)Jackson版本時(shí),最常見(jiàn)的問(wèn)題是依賴(lài)沖突,在實(shí)際項(xiàng)目中往往會(huì)遇到各種問(wèn)題,這篇文章主要介紹了Jackson3遷移核心注意點(diǎn)總結(jié)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2026-05-05
  • Spring?data?jpa緩存機(jī)制使用總結(jié)

    Spring?data?jpa緩存機(jī)制使用總結(jié)

    這篇文章主要介紹了Spring?data?jpa緩存機(jī)制使用總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Java實(shí)現(xiàn)文件復(fù)制及文件夾復(fù)制幾種常用的方式

    Java實(shí)現(xiàn)文件復(fù)制及文件夾復(fù)制幾種常用的方式

    這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)文件復(fù)制及文件夾復(fù)制幾種常用的方式,java復(fù)制文件的方式其實(shí)有不少種,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • Spring如何配置文件動(dòng)態(tài)讀取pom.xml中的屬性

    Spring如何配置文件動(dòng)態(tài)讀取pom.xml中的屬性

    在項(xiàng)目開(kāi)發(fā)中,經(jīng)常需要將pom.xml中的屬性動(dòng)態(tài)傳遞給Spring配置文件,實(shí)現(xiàn)這一需求,可通過(guò)Maven的資源過(guò)濾功能,配置占位符替換,具體方法包括:在pom.xml中啟用filtering,然后在Spring配置文件中通過(guò)${property}方式引用屬性
    2024-10-10
  • springboot集成mybatisPlus+多數(shù)據(jù)源的實(shí)現(xiàn)示例

    springboot集成mybatisPlus+多數(shù)據(jù)源的實(shí)現(xiàn)示例

    這篇文章主要介紹了springboot集成mybatisPlus+多數(shù)據(jù)源的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java實(shí)現(xiàn)ByteArray與String互轉(zhuǎn)的常見(jiàn)轉(zhuǎn)換方法

    Java實(shí)現(xiàn)ByteArray與String互轉(zhuǎn)的常見(jiàn)轉(zhuǎn)換方法

    在現(xiàn)代 Java 開(kāi)發(fā)中,處理字節(jié)數(shù)據(jù)(byte[])和字符串(String)之間的轉(zhuǎn)換是一項(xiàng)常見(jiàn)且至關(guān)重要的任務(wù),無(wú)論是網(wǎng)絡(luò)通信、文件操作、加密解密還是序列化反序列化,我們都需要在 byte[] 和 String 之間進(jìn)行高效、準(zhǔn)確的轉(zhuǎn)換,所以本文介紹了ByteArray與String互轉(zhuǎn)方法
    2025-12-12

最新評(píng)論

陕西省| 当雄县| 洪洞县| 大连市| 阿尔山市| 铜陵市| 福建省| 博野县| 侯马市| 中方县| 蛟河市| 临夏市| 无为县| 三都| 通山县| 丰镇市| 碌曲县| 吉水县| 赤城县| 通化县| 洞头县| 会理县| 榆树市| 牙克石市| 阳信县| 和田县| 齐齐哈尔市| 长顺县| 泰来县| 永州市| 涿州市| 焦作市| 汶川县| 麦盖提县| 塔河县| 汉寿县| 新营市| 屯留县| 郯城县| 新兴县| 尼木县|