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

Fluent Mybatis 批量更新的使用

 更新時(shí)間:2021年08月05日 10:06:47   作者:稻草江南  
本文主要介紹了Fluent Mybatis 批量更新的使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

批量更新同一張表的數(shù)據(jù)

更新多條數(shù)據(jù),每條數(shù)據(jù)都不一樣

背景描述

通常需要一次更新多條數(shù)據(jù)有兩個(gè)方式

在業(yè)務(wù)代碼中循環(huán)遍歷,逐條更新
一次性更新所有數(shù)據(jù), 采用批量sql方式,一次執(zhí)行。

更準(zhǔn)確的說是一條sql語句來更新所有數(shù)據(jù),逐條更新的操作放到數(shù)據(jù)庫端,在業(yè)務(wù)代碼端展現(xiàn)的就是一次性更新所有數(shù)據(jù)。

這兩種方式各有利弊,程序中for循環(huán)實(shí)現(xiàn)就不說了,這里主要介紹第二種方式在fluent mybatis中的實(shí)現(xiàn),以及和mybatis實(shí)現(xiàn)的對(duì)比。

java中for循環(huán)實(shí)現(xiàn)方式

public class UpdateBatchTest extends BaseTest {
    @Autowired
    private StudentMapper mapper;

    @Test
    public void testBatchJavaEach() {
        /** 構(gòu)造多個(gè)更新 **/
        List<IUpdate> updates = this.newListUpdater();
        for (IUpdate update : updates) {
            mapper.updateBy(update);
        }
    }
    
    /**
     * 構(gòu)造多個(gè)更新操作
     */
    private List<IUpdate> newListUpdater() {
        StudentUpdate update1 = new StudentUpdate()
            .update.userName().is("user name23").end()
            .where.id().eq(23L).end();
        StudentUpdate update2 = new StudentUpdate()
            .update.userName().is("user name24").end()
            .where.id().eq(24L).end();
        return Arrays.asList(update1, update2);
    }
}

這種方式在大批量更新時(shí), 最大的問題就是效率,逐條更新,每次都會(huì)連接數(shù)據(jù)庫,然后更新,再釋放連接資源。

一條SQL,服務(wù)端逐條更新

mybatis實(shí)現(xiàn)方式

通過mybatis提供的循環(huán)標(biāo)簽,一次構(gòu)造多條update的sql,一次提交服務(wù)器進(jìn)行執(zhí)行。

<update id="updateStudentBatch"  parameterType="java.util.List">  
    <update id="updateStudentBatch"  parameterType="java.util.List">
        <foreach collection="list" item="item" index="index" open="" close="" separator=";">
            update student
            <set>
                user_name=#{item.userName}
            </set>
            where id = #{item.id}
        </foreach>
    </update>   
</update>

定義Mapper

public interface StudentBatchMapper {
    void updateStudentBatch(List list);
}

執(zhí)行測試驗(yàn)證

public class UpdateBatchTest extends BaseTest {
    @Autowired
    private StudentBatchMapper batchMapper;

    @Test
    public void updateStudentBatch() {
        List<StudentEntity> students = Arrays.asList(
            new StudentEntity().setId(23L).setUserName("user name23"),
            new StudentEntity().setId(24L).setUserName("user name24"));
        batchMapper.updateStudentBatch(students);
        /** 驗(yàn)證SQL參數(shù) **/
        db.table(ATM.table.student).query().eqDataMap(ATM.dataMap.student.table(2)
            .id.values(23L, 24L)
            .userName.values("user name23", "user name24")
        );
    }
}

使用FluentMybatis實(shí)現(xiàn)方式

使用fluent mybatis進(jìn)行批量更新很簡單,只需要在#updateBy方法中傳入 IUpdate數(shù)組即可

public class UpdateBatchTest extends BaseTest {
    @Autowired
    private StudentMapper mapper;

    @DisplayName("批量更新同一張表")
    @Test
    public void testUpdateBatch_same() {
        IUpdate[] updates = this.newListUpdater().toArray(new IUpdate[0]);
        mapper.updateBy(updates);
        /** 驗(yàn)證SQL語句 **/
        db.sqlList().wantFirstSql().eq("" +
                "UPDATE student SET gmt_modified = now(), user_name = ? WHERE id = ?; " +
                "UPDATE student SET gmt_modified = now(), user_name = ? WHERE id = ?"
            , StringMode.SameAsSpace);
        /** 驗(yàn)證SQL參數(shù) **/
        db.table(ATM.table.student).query().eqDataMap(ATM.dataMap.student.table(2)
            .id.values(23L, 24L)
            .userName.values("user name23", "user name24")
        );
    }
}

要實(shí)現(xiàn)批量更新,首先得設(shè)置mysql支持批量操作,在jdbc url鏈接中附加&allowMultiQueries=true屬性

例如:

jdbc:mysql://localhost:3306/testdb?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true

使用mysql的Case When then方式更新

UPDATE student 
SET gmt_modified = now(),
address = case id when 1 then 'address 1' when 2 then 'address 2' when 3 then 'address 3' end
WHERE id in (1, 2, 3)

上面的sql語句使用mysql的case when then語法實(shí)現(xiàn)的批量更新3條記錄,并且根據(jù)id的值不同,設(shè)置不同的address值。

mybatis原生實(shí)現(xiàn)方式

如果使用mybatis的xml語法來實(shí)現(xiàn),xml文件就需要表達(dá)為下面方式:

xml文件

<update id="updateBatchByIds" parameterType="list">
    update student
    <trim prefix="set" suffixOverrides=",">
        <trim prefix="address =case id" suffix="end,">
            <foreach collection="list" item="item" index="index">
                <if test="item.id!=null">
                    when #{item.id} then #{item.address}
                </if>
            </foreach>
        </trim>
    </trim>
    <trim prefix="age =case id" suffix="end,">
        <foreach collection="list" item="item" index="index">
            <if test="item.id!=null">
                when #{item.id} then #{item.age}
            </if>
        </foreach>
    </trim>
    where id in
    <foreach collection="list" item="item" index="index" separator="," open="(" close=")">
        #{item.id}
    </foreach>
</update>

定義Mapper

public interface StudentBatchMapper {
    int updateBatchByIds(List<StudentEntity> list);
}

驗(yàn)證

public class CaseFuncTest extends BaseTest {
    @Autowired
    private StudentBatchMapper batchMapper;

    @Test
    public void test_mybatis_batch() {
        batchMapper.updateBatchByIds(Arrays.asList(
            new StudentEntity().setId(1L).setAddress("address 1").setAge(23),
            new StudentEntity().setId(2L).setAddress("address 2").setAge(24),
            new StudentEntity().setId(3L).setAddress("address 3").setAge(25)
        ));
        /** 驗(yàn)證執(zhí)行的SQL語句 **/
        db.sqlList().wantFirstSql().eq("" +
                "update student " +
                "set address =case id when ? then ? when ? then ? when ? then ? end, " +
                "age =case id when ? then ? when ? then ? when ? then ? end " +
                "where id in ( ? , ? , ? )"
            , StringMode.SameAsSpace);
    }
}

使用Fluent Mybatis實(shí)現(xiàn)方式

public class CaseFuncTest extends BaseTest {
    @Autowired
    private StudentMapper mapper;

    @Test
    public void test_fluentMybatisBatch() throws Exception {
        final String CaseWhen = "case id " +
            "when 1 then ? " +
            "when 2 then ? " +
            "else ? end";
        StudentUpdate update = new StudentUpdate()
            .update.address().applyFunc(CaseWhen, "address 1", "address 2", "address 3")
            .set.age().applyFunc(CaseWhen, 23, 24, 25)
            .end()
            .where.id().in(new int[]{1, 2, 3}).end();
        mapper.updateBy(update);
        /** 驗(yàn)證執(zhí)行的SQL語句 **/
        db.sqlList().wantFirstSql()
            .eq("UPDATE student " +
                    "SET gmt_modified = now(), " +
                    "address = case id when 1 then ? when 2 then ? else ? end, " +
                    "age = case id when 1 then ? when 2 then ? else ? end " +
                    "WHERE id IN (?, ?, ?)",
                StringMode.SameAsSpace);
    }
}

只需要在applyFunc中傳入case when語句,和對(duì)應(yīng)的參數(shù)(對(duì)應(yīng)case when語句中的預(yù)編譯占位符'?')

如果業(yè)務(wù)入口傳入的是Entity List或者M(jìn)ap List,可以使用java8的stream功能處理成數(shù)組,示例如下:

public class CaseFuncTest extends BaseTest {
    @Autowired
    private StudentMapper mapper;

    @Test
    public void test_fluentMybatisBatch2() throws Exception {
        List<StudentEntity> students = Arrays.asList(
            new StudentEntity().setId(1L).setAddress("address 1").setAge(23),
            new StudentEntity().setId(2L).setAddress("address 2").setAge(24),
            new StudentEntity().setId(3L).setAddress("address 3").setAge(25));
        final String CaseWhen = "case id " +
            "when 1 then ? " +
            "when 2 then ? " +
            "else ? end";
        StudentUpdate update = new StudentUpdate()
            .update.address().applyFunc(CaseWhen, getFields(students, StudentEntity::getAddress))
            .set.age().applyFunc(CaseWhen, getFields(students, StudentEntity::getAge))
            .end()
            .where.id().in(getFields(students, StudentEntity::getId)).end();
        mapper.updateBy(update);
        // 驗(yàn)證SQL語句
        db.sqlList().wantFirstSql()
            .eq("UPDATE student " +
                    "SET gmt_modified = now(), " +
                    "address = case id when 1 then ? when 2 then ? else ? end, " +
                    "age = case id when 1 then ? when 2 then ? else ? end " +
                    "WHERE id IN (?, ?, ?)",
                StringMode.SameAsSpace);
        // 驗(yàn)證參數(shù)
        db.sqlList().wantFirstPara()
            .eqReflect(new Object[]{"address 1", "address 2", "address 3", 23, 24, 25, 1L, 2L, 3L});
    }

    private Object[] getFields(List<StudentEntity> students, Function<StudentEntity, Object> getField) {
        return students.stream().map(getField).toArray(Object[]::new);
    }
}

使用Fluent Mybatis無需額外編寫xml文件和mapper(使用框架生成的Mapper文件就夠了)。在業(yè)務(wù)邏輯上不至于因?yàn)橛蓄~外的xml文件,而產(chǎn)生割裂感。

批量更新不同的表數(shù)據(jù)

上面的例子使用mybatis和fluent mybatis演示的如果通過不同方法批量更新同一張表的數(shù)據(jù),在fluent mybatis的更新其實(shí)不限定于同一張表,

在#updateBy(IUpdate... updates)函數(shù)可以傳入任意表更新.

public class UpdateBatchTest extends BaseTest {
    @Autowired
    private StudentMapper mapper;

    @DisplayName("批量更新不同表")
    @Test
    public void testUpdateBatch_different() {
        StudentUpdate update1 = new StudentUpdate()
            .update.userName().is("user name23").end()
            .where.id().eq(23L).end();
        HomeAddressUpdate update2 = new HomeAddressUpdate()
            .update.address().is("address 24").end()
            .where.id().eq(24L).end();
        
        /** 執(zhí)行不同表的批量更新 **/
        mapper.updateBy(update1, update2);
    
        /** 驗(yàn)證實(shí)際執(zhí)行的預(yù)編譯SQL語句**/
        db.sqlList().wantFirstSql().eq("" +
                "UPDATE student SET gmt_modified = now(), user_name = ? WHERE id = ?; " +
                "UPDATE home_address SET gmt_modified = now(), address = ? WHERE id = ?", StringMode.SameAsSpace);
        db.table(ATM.table.student).query().eqDataMap(ATM.dataMap.student.table(2)
            .id.values(23L, 24L)
            .userName.values("user name23", "user")
        );
        /** 驗(yàn)證實(shí)際執(zhí)行預(yù)編譯SQL入?yún)⒅?**/
        db.table(ATM.table.homeAddress).query().eqDataMap(ATM.dataMap.homeAddress.table(2)
            .id.values(23, 24)
            .address.values("address", "address 24")
        );
    }
}

示例更新了2張表: student 和 home_address

參考

Fluent MyBatis地址
Fluent MyBatis文檔

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

相關(guān)文章

  • SpringBoot兩種方式接入DeepSeek的實(shí)現(xiàn)

    SpringBoot兩種方式接入DeepSeek的實(shí)現(xiàn)

    本文主要介紹了SpringBoot兩種方式接入DeepSeek的實(shí)現(xiàn),包括HttpClient方式和基于spring-ai-openai的方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • SpringBoot內(nèi)置tomcat參數(shù)調(diào)優(yōu)的實(shí)現(xiàn)

    SpringBoot內(nèi)置tomcat參數(shù)調(diào)優(yōu)的實(shí)現(xiàn)

    springboot內(nèi)置了tomcat, 并給我們?cè)O(shè)置了默認(rèn)參數(shù), 我們?cè)趺礃有薷膕pringboot內(nèi)置的tomcat參數(shù),本文就詳細(xì)的來介紹一下,感興趣的可以了解一下
    2023-09-09
  • 解決lambda表達(dá)式內(nèi)出現(xiàn)異常無法throw拋出的問題

    解決lambda表達(dá)式內(nèi)出現(xiàn)異常無法throw拋出的問題

    這篇文章主要介紹了lambda表達(dá)式內(nèi)出現(xiàn)異常無法throw拋出的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Spring框架中ImportBeanDefinitionRegistrar的應(yīng)用詳解

    Spring框架中ImportBeanDefinitionRegistrar的應(yīng)用詳解

    這篇文章主要介紹了Spring框架中ImportBeanDefinitionRegistrar的應(yīng)用詳解,如果實(shí)現(xiàn)了ImportSelector接口,在配置類中被@Import加入到Spring容器中以后,Spring容器就會(huì)把ImportSelector接口方法返回的字符串?dāng)?shù)組中的類new出來對(duì)象然后放到工廠中去,需要的朋友可以參考下
    2024-01-01
  • java如何刪除以逗號(hào)隔開的字符串中某一個(gè)值

    java如何刪除以逗號(hào)隔開的字符串中某一個(gè)值

    這篇文章主要介紹了java如何刪除以逗號(hào)隔開的字符串中某一個(gè)值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 詳解jvm中的標(biāo)量替換

    詳解jvm中的標(biāo)量替換

    這篇文章主要介紹了詳解jvm中的標(biāo)量替換,幫助大家更好的理解和使用Java虛擬機(jī),感興趣的朋友可以了解下
    2020-09-09
  • Java調(diào)用SSE流式接口并流式返回給前端實(shí)現(xiàn)打字輸出效果

    Java調(diào)用SSE流式接口并流式返回給前端實(shí)現(xiàn)打字輸出效果

    在Web開發(fā)中,有時(shí)我們需要將文件以流的形式返回給前端,下面這篇文章主要給大家介紹了關(guān)于Java調(diào)用SSE流式接口并流式返回給前端實(shí)現(xiàn)打字輸出效果的相關(guān)資料,需要的朋友可以參考下
    2024-08-08
  • Java數(shù)據(jù)類型的規(guī)則

    Java數(shù)據(jù)類型的規(guī)則

    這篇文章主要介紹了Java數(shù)據(jù)類型的規(guī)則的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-12-12
  • Springboot消除switch-case過程解析

    Springboot消除switch-case過程解析

    這篇文章主要介紹了Springboot消除switch-case過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Java下載文件時(shí)文件名亂碼問題解決辦法

    Java下載文件時(shí)文件名亂碼問題解決辦法

    我最近在開發(fā)時(shí)遇到了文件另存為時(shí)文件名出現(xiàn)亂碼,在火狐上正常的文件名,在IE中又出現(xiàn)亂碼問題,然后好不容易在IE下調(diào)試好了文件名亂碼問題,在火狐下又出現(xiàn)亂碼,最后終于感覺這樣是能解決了。具體如下:
    2013-04-04

最新評(píng)論

浑源县| 松桃| 旌德县| 鄱阳县| 密山市| 新宾| 宜兰市| 财经| 年辖:市辖区| 大余县| 铅山县| 鹤峰县| 满洲里市| 民权县| 微博| 民县| 青川县| 连南| 阿巴嘎旗| 武平县| 岑溪市| 东城区| 新晃| 司法| 泾川县| 盐山县| 大方县| 故城县| 夏河县| 宣恩县| 松江区| 商都县| 江达县| 隆安县| 高密市| 吉水县| 大荔县| 内黄县| 临海市| 东乡族自治县| 芜湖市|