一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Fluent Mybatis 批量更新的使用

Fluent Mybatis 批量更新的使用

2021-11-08 11:03稻草江南 Java教程

本文主要介紹了Fluent Mybatis 批量更新的使用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

批量更新同一張表的數據

更新多條數據,每條數據都不一樣

背景描述

通常需要一次更新多條數據有兩個方式

在業務代碼中循環遍歷,逐條更新
一次性更新所有數據, 采用批量sql方式,一次執行。

更準確的說是一條sql語句來更新所有數據,逐條更新的操作放到數據庫端,在業務代碼端展現的就是一次性更新所有數據。

這兩種方式各有利弊,程序中for循環實現就不說了,這里主要介紹第二種方式在fluent mybatis中的實現,以及和mybatis實現的對比。

java中for循環實現方式

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class UpdateBatchTest extends BaseTest {
    @Autowired
    private StudentMapper mapper;
 
    @Test
    public void testBatchJavaEach() {
        /** 構造多個更新 **/
        List<IUpdate> updates = this.newListUpdater();
        for (IUpdate update : updates) {
            mapper.updateBy(update);
        }
    }
    
    /**
     * 構造多個更新操作
     */
    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);
    }
}

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

一條SQL,服務端逐條更新

mybatis實現方式

通過mybatis提供的循環標簽,一次構造多條update的sql,一次提交服務器進行執行。

?
1
2
3
4
5
6
7
8
9
10
11
<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

?
1
2
3
public interface StudentBatchMapper {
    void updateStudentBatch(List list);
}

執行測試驗證

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
        /** 驗證SQL參數 **/
        db.table(ATM.table.student).query().eqDataMap(ATM.dataMap.student.table(2)
            .id.values(23L, 24L)
            .userName.values("user name23", "user name24")
        );
    }
}

使用FluentMybatis實現方式

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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);
        /** 驗證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);
        /** 驗證SQL參數 **/
        db.table(ATM.table.student).query().eqDataMap(ATM.dataMap.student.table(2)
            .id.values(23L, 24L)
            .userName.values("user name23", "user name24")
        );
    }
}

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

例如:

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

使用mysql的Case When then方式更新

?
1
2
3
4
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語法實現的批量更新3條記錄,并且根據id的值不同,設置不同的address值。

mybatis原生實現方式

如果使用mybatis的xml語法來實現,xml文件就需要表達為下面方式:

xml文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<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

?
1
2
3
public interface StudentBatchMapper {
    int updateBatchByIds(List<StudentEntity> list);
}

驗證

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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)
        ));
        /** 驗證執行的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實現方式

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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);
        /** 驗證執行的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語句,和對應的參數(對應case when語句中的預編譯占位符'?')

如果業務入口傳入的是Entity List或者Map List,可以使用java8的stream功能處理成數組,示例如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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);
        // 驗證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);
        // 驗證參數
        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文件就夠了)。在業務邏輯上不至于因為有額外的xml文件,而產生割裂感。

批量更新不同的表數據

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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();
        
        /** 執行不同表的批量更新 **/
        mapper.updateBy(update1, update2);
    
        /** 驗證實際執行的預編譯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")
        );
        /** 驗證實際執行預編譯SQL入參值 **/
        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文檔

到此這篇關于Fluent Mybatis 批量更新的使用的文章就介紹到這了,更多相關Fluent Mybatis 批量更新內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://juejin.cn/post/6923914096467410958

延伸 · 閱讀

精彩推薦
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
主站蜘蛛池模板: 精品国产区 | 国产免费看黄的私人影院 | 337p大尺度啪啪人体午夜2020 | 日本中文字幕在线精品 | 亚洲国产精品福利片在线观看 | 亚洲高清无在码在线电影 | 22222色男人的天堂 | 国产精品久久久久久久牛牛 | mm在线 | 香蕉精品 | 国产精品xxxav免费视频 | 日韩欧美中文字幕一区 | bbwfreehd女厕所ved| 天美视频在线 | 黑人粗长巨茎小说 | ssni-497新任美脚女教师 | 超逼网| 国产大秀视频一区二区三区 | 美女扒开粉嫩尿口漫画 | 国产成人免费高清激情明星 | 99九九成人免费视频精品 | 亚洲高清视频在线观看 | 邪恶肉肉全彩色无遮琉璃神社 | 国产人妖xxxxx免费看 | 92国产福利视频一区二区 | 亚洲免费视频在线观看 | 欧美一级裸片 | 污书屋| aigao视频 | 99在线免费观看 | 久久精品国产亚洲AV热无遮挡 | 99ri国产在线 | 日本久久啪啪婷婷激情五月 | 色777777女人色 | 草逼视频网址 | china精品对白普通话 | 俄罗斯美女毛茸茸bbwbbw | 人人爽人人草 | 风间由美理论片在线观看 | 国产图片综合区 | h片免费网站 |