欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MybatisPlus實(shí)現(xiàn)真正批量插入的詳細(xì)步驟

 更新時間:2024年10月08日 10:10:23   作者:總是學(xué)不會.  
在數(shù)據(jù)庫操作中,批量插入是提升效率的重要手段,MyBatis-Plus提供了多種批量插入方法,但默認(rèn)的saveBatch方法效率并不高,文章介紹了通過手動拼接SQL、使用IService接口以及自定義insertBatchSomeColumn方法進(jìn)行優(yōu)化,以實(shí)現(xiàn)更高效的批量插入,并給出了性能優(yōu)化建議

在實(shí)際開發(fā)中,批量插入是提高數(shù)據(jù)處理效率的常用手段。MyBatis-Plus 作為 MyBatis 的增強(qiáng)工具,提供了多種方式來實(shí)現(xiàn)批量插入。然而,默認(rèn)的 saveBatch 方法在底層實(shí)際上是逐條插入,性能上并不理想。本文將詳細(xì)介紹如何通過 MyBatis-Plus 實(shí)現(xiàn)真正高效的批量插入,包括手動拼接 SQL、使用 IService 接口以及自定義 insertBatchSomeColumn 方法,并提供性能優(yōu)化建議。

一、通過 XML 手動拼接 SQL 實(shí)現(xiàn)批量插入

優(yōu)勢

  • 高效:一次性執(zhí)行批量插入,減少數(shù)據(jù)庫交互次數(shù)。
  • 靈活:可以根據(jù)需要選擇性插入部分字段,減少不必要的數(shù)據(jù)傳輸。

缺點(diǎn)

  • 維護(hù)成本高:每個表都需要手動編寫對應(yīng)的 XML SQL。
  • 不支持自動生成主鍵:如果表中有自增主鍵,需額外處理。

實(shí)現(xiàn)步驟

編寫 Mapper XML 文件

history_summary 表為例,編寫批量插入的 XML:

<insert id="insertBatch" parameterType="java.util.List">
    INSERT INTO history_summary
    (key_id, business_no, status, customer_id, instruction_id, customer_business_no, dept_id, doc_type_id, doc_page_no, document_version, result_mongo_doc_id, is_active, problem_status, tran_source, document_count_page, is_rush, is_deleted, document_tran_time, customer_tran_time, preprocess_recv_time, delete_time, create_time, complete_time, version, zip_name, document_no, new_task_type, handle_begin_time, handle_end_time, cost_seconds, char_num, ocr_result_mongo_id, reserve_text2, reserve_text3, reserve_text1, reserve_text4, reserve_text5, ocr_result_type, repeat_status, form_version, repetition_count)
    VALUES
    <foreach collection="list" item="item" separator=",">
        (#{item.keyId}, #{item.businessNo}, #{item.status}, #{item.customerId}, #{item.instructionId}, #{item.customerBusinessNo}, #{item.deptId}, #{item.docTypeId}, #{item.docPageNo}, #{item.documentVersion}, #{item.resultMongoDocId}, #{item.isActive}, #{item.problemStatus}, #{item.tranSource}, #{item.documentCountPage}, #{item.isRush}, #{item.isDeleted}, #{item.documentTranTime}, #{item.customerTranTime}, #{item.preprocessRecvTime}, #{item.deleteTime}, #{item.createTime}, #{item.completeTime}, #{item.version}, #{item.zipName}, #{item.documentNo}, #{item.newTaskType}, #{item.handleBeginTime}, #{item.handleEndTime}, #{item.costSeconds}, #{item.charNum}, #{item.ocrResultMongoId}, #{item.reserveText2}, #{item.reserveText3}, #{item.reserveText1}, #{item.reserveText4}, #{item.reserveText5}, #{item.ocrResultType}, #{item.repeatStatus}, #{item.formVersion}, #{item.repetitionCount})
    </foreach>
</insert>

在 Mapper 接口中定義批量插入方法

public interface historySummaryMapper extends BaseMapper<historySummary> {
    @Insert({
        "<script>",
        "INSERT INTO history_summary ",
        "(key_id, business_no, status, customer_id, instruction_id, customer_business_no, dept_id, doc_type_id, doc_page_no, document_version, result_mongo_doc_id, is_active, problem_status, tran_source, document_count_page, is_rush, is_deleted, document_tran_time, customer_tran_time, preprocess_recv_time, delete_time, create_time, complete_time, version, zip_name, document_no, new_task_type, handle_begin_time, handle_end_time, cost_seconds, char_num, ocr_result_mongo_id, reserve_text2, reserve_text3, reserve_text1, reserve_text4, reserve_text5, ocr_result_type, repeat_status, form_version, repetition_count)",
        "VALUES ",
        "<foreach collection='list' item='item' index='index' separator=','>",
        "(#{item.keyId}, #{item.businessNo}, #{item.status}, #{item.customerId}, #{item.instructionId}, #{item.customerBusinessNo}, #{item.deptId}, #{item.docTypeId}, #{item.docPageNo}, #{item.documentVersion}, #{item.resultMongoDocId}, #{item.isActive}, #{item.problemStatus}, #{item.tranSource}, #{item.documentCountPage}, #{item.isRush}, #{item.isDeleted}, #{item.documentTranTime}, #{item.customerTranTime}, #{item.preprocessRecvTime}, #{item.deleteTime}, #{item.createTime}, #{item.completeTime}, #{item.version}, #{item.zipName}, #{item.documentNo}, #{item.newTaskType}, #{item.handleBeginTime}, #{item.handleEndTime}, #{item.costSeconds}, #{item.charNum}, #{item.ocrResultMongoId}, #{item.reserveText2}, #{item.reserveText3}, #{item.reserveText1}, #{item.reserveText4}, #{item.reserveText5}, #{item.ocrResultType}, #{item.repeatStatus}, #{item.formVersion}, #{item.repetitionCount})",
        "</foreach>",
        "</script>"
    })
    int insertBatch(@Param("list") List<historySummary> list);
}

在 Service 層調(diào)用批量插入方法

@Service
public class historySummaryServiceImpl extends ServiceImpl<historySummaryMapper, historySummary> implements IhistorySummaryService {
    @Autowired
    private historySummaryMapper mapper;
    @Transactional(rollbackFor = Exception.class)
    public boolean batchInsert(List<historySummary> list) {
        int result = mapper.insertBatch(list);
        return result > 0;
    }
}

使用示例

@RestController
@RequestMapping("/api/business")
public class BusinessController {
    @Autowired
    private IhistorySummaryService service;
    @PostMapping("/batchInsert")
    public ResponseEntity<String> batchInsert(@RequestBody List<historySummary> list) {
        boolean success = service.batchInsert(list);
        if (success) {
            return ResponseEntity.ok("批量插入成功");
        } else {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("批量插入失敗");
        }
    }
}

看到這里應(yīng)該頭皮發(fā)麻了吧。這也是我為什么想分享這篇文章的原因!?。?/p>

涉及到多字段批量插入,還是推薦下面的方法。

二、使用 MyBatis-Plus IService 接口的 saveBatch 方法

MyBatis-Plus 提供的 saveBatch 方法簡化了批量插入的操作,但其底層實(shí)際上是逐條插入,因此在處理大量數(shù)據(jù)時性能不佳。

優(yōu)勢

  • 簡便易用:無需手動編寫 SQL,直接調(diào)用接口方法即可。
  • 自動事務(wù)管理:內(nèi)置事務(wù)支持,確保數(shù)據(jù)一致性。

缺點(diǎn)

  • 性能有限:底層逐條插入,面對大數(shù)據(jù)量時效率較低。
  • 批量大小受限:默認(rèn)批量大小可能不適用于所有場景,需要手動調(diào)整。

提升性能的方法

配置數(shù)據(jù)庫連接參數(shù)

在數(shù)據(jù)庫的連接 URL 中添加 rewriteBatchedStatements=true,啟用批量重寫功能,提升批量插入性能。

spring.datasource.url=jdbc:mysql://localhost:3306/your_database?rewriteBatchedStatements=true

調(diào)整批量大小

在調(diào)用 saveBatch 方法時,合理設(shè)置批量大?。ㄈ?1000 條一批),以平衡性能和資源消耗。

@Transactional(rollbackFor = {Exception.class})
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);
    });
}

三、insertBatchSomeColumn 方法實(shí)現(xiàn)批量插入

為了實(shí)現(xiàn)真正高效的批量插入,可以使用 insertBatchSomeColumn 方法,實(shí)現(xiàn)一次性批量插入。

優(yōu)勢

  • 高效:一次性執(zhí)行批量插入,減少數(shù)據(jù)庫交互次數(shù)。
  • 靈活:可選擇性插入部分字段,優(yōu)化數(shù)據(jù)傳輸。(通過實(shí)體類屬性)

實(shí)現(xiàn)步驟

1. 自定義SQL注入器實(shí)現(xiàn)DefaultSqlInjector,添加InsertBatchSomeColumn方法

public class MySqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        return methodList;
    }
}

2. 將MySqlInjector注入到Bean中

@Configuration
public class MyBatisConfig {
    @Bean
    public MySqlInjector sqlInjector() {
        return new MySqlInjector();
    }
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分頁插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        //添加樂觀鎖插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

3. 繼承Mybatis-plus的BaseMapper,添加插入方法

public interface MyBaseMapper<T> extends BaseMapper<T> {
    int insertBatchSomeColumn(Collection<T> entityList);
}
@Mapper
public interface WorkingBusinessHistoryMapper extends MyBaseMapper<BusinessHistory> {
}

注意事項(xiàng)

  • 批量大小:根據(jù)數(shù)據(jù)庫和應(yīng)用的性能,合理設(shè)置批量插入的大小,避免單次插入過多數(shù)據(jù)導(dǎo)致內(nèi)存溢出或數(shù)據(jù)庫壓力過大。
  • 事務(wù)管理:確保批量操作在事務(wù)中執(zhí)行,以保證數(shù)據(jù)的一致性和完整性。
  • 錯誤處理:在批量操作中,如果某條記錄插入失敗,需要有相應(yīng)的機(jī)制進(jìn)行回滾或記錄失敗信息。

四、性能優(yōu)化建議

為了進(jìn)一步提升批量插入的性能,可以采取以下優(yōu)化措施:

1. 開啟批量重寫功能

在數(shù)據(jù)庫的連接 URL 中添加 rewriteBatchedStatements=true,以優(yōu)化批量插入的性能。

spring.datasource.url=jdbc:mysql://localhost:3306/your_database?rewriteBatchedStatements=true

2. 合理設(shè)置批量大小

根據(jù)具體業(yè)務(wù)場景和數(shù)據(jù)庫性能,調(diào)整批量大?。ㄈ?1000 條一批),避免單次插入過多數(shù)據(jù)。

int batchSize = 1000;
for (int i = 0; i < list.size(); i += batchSize) {
    List<historySummary> batchList = list.subList(i, Math.min(i + batchSize, list.size()));
    mapper.insertBatchSomeColumn(batchList);
}

3. 使用事務(wù)管理

確保批量操作在事務(wù)中執(zhí)行,避免部分插入成功導(dǎo)致數(shù)據(jù)不一致。

@Transactional(rollbackFor = Exception.class)
public boolean batchInsert(List<historySummary> list) {
    int result = mapper.insertBatchSomeColumn(list);
    return result > 0;
}

4. 索引優(yōu)化

對插入頻繁的表,合理設(shè)計(jì)索引,避免過多不必要的索引影響插入性能。盡量減少在批量插入時的索引數(shù)量,插入完成后再創(chuàng)建必要的索引。

5. 禁用自動提交

在批量插入過程中,禁用自動提交,減少事務(wù)提交的次數(shù),提高性能。

jdbcTemplate.execute((ConnectionCallback<Void>) connection -> {
    connection.setAutoCommit(false);
    // 執(zhí)行批量插入操作
    connection.commit();
    return null;
});

參考

MybatisPlus自定義insertBatchSomeColumn實(shí)現(xiàn)真正批量插入 - CSDN博客

MybatisPlus如何實(shí)現(xiàn)insertBatchSomeColumn進(jìn)行批量增加 - 億速云

MyBatis-Plus 官方文檔

MySQL Connector/J Documentation

到此這篇關(guān)于MybatisPlus實(shí)現(xiàn)真正批量插入的文章就介紹到這了,更多相關(guān)MybatisPlus批量插入內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java使用JavaMail API發(fā)送和接收郵件的代碼示例

    Java使用JavaMail API發(fā)送和接收郵件的代碼示例

    JavaMail是Oracle甲骨文開發(fā)的Java郵件類API,支持多種郵件協(xié)議,這里我們就來看一下Java使用JavaMail API發(fā)送和接收郵件的代碼示例
    2016-06-06
  • 關(guān)于springboot2整合lettuce啟動卡住問題的解決方法

    關(guān)于springboot2整合lettuce啟動卡住問題的解決方法

    Lettuce和Jedis的都是連接Redis Server的客戶端程序,下面這篇文章主要給大家介紹了關(guān)于springboot2整合lettuce啟動卡住問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-12-12
  • Java 二叉樹遍歷特別篇之Morris遍歷

    Java 二叉樹遍歷特別篇之Morris遍歷

    二叉樹的遍歷(traversing binary tree)是指從根結(jié)點(diǎn)出發(fā),按照某種次序依次訪問二叉樹中所有的結(jié)點(diǎn),使得每個結(jié)點(diǎn)被訪問依次且僅被訪問一次。四種遍歷方式分別為:先序遍歷、中序遍歷、后序遍歷、層序遍歷
    2021-11-11
  • java必懂的冷知識點(diǎn)之Base64加密與解密

    java必懂的冷知識點(diǎn)之Base64加密與解密

    這篇文章主要介紹了java必懂的冷知識點(diǎn)之Base64加密與解密的相關(guān)資料,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • 使用Spring實(shí)現(xiàn)@Value注入靜態(tài)字段

    使用Spring實(shí)現(xiàn)@Value注入靜態(tài)字段

    這篇文章主要介紹了使用Spring實(shí)現(xiàn)@Value注入靜態(tài)字段方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java排序的那些事之sort方法的使用詳解

    Java排序的那些事之sort方法的使用詳解

    sort方法用于對數(shù)組的元素進(jìn)行排序。排序順序可以是字母或數(shù)字,并按升序或降序。默認(rèn)排序順序?yàn)榘醋帜干?,?dāng)數(shù)字是按字母順序排列時"40"將排在"5"前面。使用數(shù)字排序,你必須通過一個函數(shù)作為參數(shù)來調(diào)用。這些說起來可能很難理解,你可以通過本篇文章進(jìn)一步了解它
    2021-09-09
  • Java?FTP協(xié)議實(shí)現(xiàn)文件下載功能

    Java?FTP協(xié)議實(shí)現(xiàn)文件下載功能

    FTP(File?Transfer?Protocol)就是文件傳輸協(xié)議。通過FTP客戶端從遠(yuǎn)程FTP服務(wù)器上拷貝文件到本地計(jì)算機(jī)稱為下載,將本地計(jì)算機(jī)上的文件復(fù)制到遠(yuǎn)程FTP服務(wù)器上稱為上傳,上傳和下載是FTP最常用的兩個功能
    2022-11-11
  • 一文詳解Spring中的HttpMessageNotReadableException異常處理

    一文詳解Spring中的HttpMessageNotReadableException異常處理

    這篇文章主要為大家詳細(xì)介紹了Spring中的HttpMessageNotReadableException異常,分析其產(chǎn)生的原因并通過實(shí)際代碼示例展示如何有效地捕獲和處理這一異常,感興趣的可以了解下
    2025-02-02
  • shiro攔截認(rèn)證的全過程記錄

    shiro攔截認(rèn)證的全過程記錄

    Apache?Shiro是一個強(qiáng)大且易用的Java安全框架,執(zhí)行身份驗(yàn)證、授權(quán)、密碼和會話管理,下面這篇文章主要給大家介紹了關(guān)于shiro攔截認(rèn)證的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • Spring MVC 啟動過程源碼分析詳解

    Spring MVC 啟動過程源碼分析詳解

    這篇文章主要介紹了Spring MVC 啟動過程源碼分析詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07

最新評論