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

mybatis-plus 關(guān)于savebatch,saveorupdatebatch遇到的坑及解決辦法

 更新時間:2023年01月16日 10:43:59   作者:青藤追影  
本文主要介紹了mybatis-plus 關(guān)于savebatch,saveorupdatebatch遇到的坑及解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一.背景

最近mybatis-plus框架的更新,讓我們基礎(chǔ)開發(fā)中如虎添翼。其中基本的增刪改查,代碼生成器想必大家用著那叫一個爽。本人在使用中,也遇到一些坑。比如savebatch,saveorupdatebatch,看著這不是批量新增,批量新增或更新嘛,看著api進(jìn)行開發(fā),感覺也太好用啦。開發(fā)完一測試,速度跟蝸牛一樣,針對大數(shù)據(jù)量真是無法忍受。在控制臺上發(fā)現(xiàn),怎么名義上是批量插入,還是一條一條的進(jìn)行插入,難怪速度龜速。

二.解決辦法

查閱網(wǎng)上資料,大體有兩種解決方案:

(1).使用mybatis的xml,自己進(jìn)行sql語句編寫。該方法一個缺點(diǎn)是如果表的字段較多,有個幾十個字段,寫批量新增,批量新增修改的sql語句真是個噩夢。

INSERT INTO t 
    (id, age) 
VALUES 
    (3, 28),
    (4, 29) 
ON DUPLICATE KEY UPDATE
    id = VALUES(id),
    age = VALUES(age);

(2)mybatis-plus 新添加了一個sql注入器,通過sql注入器可以實(shí)現(xiàn)批量新增,批量新增修改功能。一次注入,隨時使用,使用極其方便。缺點(diǎn)就是項(xiàng)目啟動時候,會進(jìn)行sql注入器注冊,稍微影響啟動速度。

三.sql注入器實(shí)現(xiàn)批量更新,批量新增或更新功能

(1)自定義mapper接口,繼承BaseMapper,定義實(shí)現(xiàn)的方法。

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
 
import java.util.List;
 
/**
 * 根Mapper,給表Mapper繼承用的,可以自定義通用方法
 * {@link BaseMapper}
 * {@link com.baomidou.mybatisplus.extension.service.IService}
 * {@link com.baomidou.mybatisplus.extension.service.impl.ServiceImpl}
 */
public interface RootMapper<T> extends BaseMapper<T> {
 
    /**
     * 自定義批量插入
     * 如果要自動填充,@Param(xx) xx參數(shù)名必須是 list/collection/array 3個的其中之一
     */
    int insertBatch(@Param("list") List<T> list);
 
    /**
     * 自定義批量新增或更新
     * 如果要自動填充,@Param(xx) xx參數(shù)名必須是 list/collection/array 3個的其中之一
     */
    int mysqlInsertOrUpdateBath(@Param("list") List<T> list);
 
}

(2)批量插入、批量新增或更新具體方法實(shí)現(xiàn)

批量插入具體方法實(shí)現(xiàn)如下:

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
 
/**
 * 批量插入方法實(shí)現(xiàn)
 */
@Slf4j
public class InsertBatchMethod extends AbstractMethod {
    /**
     * insert into user(id, name, age) values (1, "a", 17), (2, "b", 18);
     <script>
     insert into user(id, name, age) values
     <foreach collection="list" item="item" index="index" open="(" separator="),(" close=")">
     #{item.id}, #{item.name}, #{item.age}
     </foreach>
     </script>
     */
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        final String sql = "<script>insert into %s %s values %s</script>";
        final String fieldSql = prepareFieldSql(tableInfo);
        final String valueSql = prepareValuesSql(tableInfo);
        final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
        log.debug("sqlResult----->{}", sqlResult);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
        // 第三個參數(shù)必須和RootMapper的自定義方法名一致
        return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatch", sqlSource, new NoKeyGenerator(), null, null);
    }
 
    private String prepareFieldSql(TableInfo tableInfo) {
        StringBuilder fieldSql = new StringBuilder();
        fieldSql.append(tableInfo.getKeyColumn()).append(",");
        tableInfo.getFieldList().forEach(x -> {
            fieldSql.append(x.getColumn()).append(",");
        });
        fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
        fieldSql.insert(0, "(");
        fieldSql.append(")");
        return fieldSql.toString();
    }
 
    private String prepareValuesSql(TableInfo tableInfo) {
        final StringBuilder valueSql = new StringBuilder();
        valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
        valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
        tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
        valueSql.delete(valueSql.length() - 1, valueSql.length());
        valueSql.append("</foreach>");
        return valueSql.toString();
    }
}

批量插入或更新具體方法如下:

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import org.springframework.util.StringUtils;
 
public class MysqlInsertOrUpdateBath extends AbstractMethod {
 
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        final String sql = "<script>insert into %s %s values %s ON DUPLICATE KEY UPDATE %s</script>";
        final String tableName = tableInfo.getTableName();
        final String filedSql = prepareFieldSql(tableInfo);
        final String modelValuesSql = prepareModelValuesSql(tableInfo);
        final String duplicateKeySql =prepareDuplicateKeySql(tableInfo);
        final String sqlResult = String.format(sql, tableName, filedSql, modelValuesSql,duplicateKeySql);
        //System.out.println("savaorupdatesqlsql="+sqlResult);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
        return this.addInsertMappedStatement(mapperClass, modelClass, "mysqlInsertOrUpdateBath", sqlSource, new NoKeyGenerator(), null, null);
    }
 
    /**
     * 準(zhǔn)備ON DUPLICATE KEY UPDATE sql
     * @param tableInfo
     * @return
     */
    private String prepareDuplicateKeySql(TableInfo tableInfo) {
        final StringBuilder duplicateKeySql = new StringBuilder();
        if(!StringUtils.isEmpty(tableInfo.getKeyColumn())) {
            duplicateKeySql.append(tableInfo.getKeyColumn()).append("=values(").append(tableInfo.getKeyColumn()).append("),");
        }
 
        tableInfo.getFieldList().forEach(x -> {
            duplicateKeySql.append(x.getColumn())
                    .append("=values(")
                    .append(x.getColumn())
                    .append("),");
        });
        duplicateKeySql.delete(duplicateKeySql.length() - 1, duplicateKeySql.length());
        return duplicateKeySql.toString();
    }
 
    /**
     * 準(zhǔn)備屬性名
     * @param tableInfo
     * @return
     */
    private String prepareFieldSql(TableInfo tableInfo) {
        StringBuilder fieldSql = new StringBuilder();
        fieldSql.append(tableInfo.getKeyColumn()).append(",");
        tableInfo.getFieldList().forEach(x -> {
            fieldSql.append(x.getColumn()).append(",");
        });
        fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
        fieldSql.insert(0, "(");
        fieldSql.append(")");
        return fieldSql.toString();
    }
 
    private String prepareModelValuesSql(TableInfo tableInfo){
        final StringBuilder valueSql = new StringBuilder();
        valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
        if(!StringUtils.isEmpty(tableInfo.getKeyProperty())) {
            valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
        }
        tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
        valueSql.delete(valueSql.length() - 1, valueSql.length());
        valueSql.append("</foreach>");
        return valueSql.toString();
    }
}

(3)sql注入器實(shí)現(xiàn)

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
 
import java.util.List;
 
/**
 * 自定義方法SQL注入器
 */
public class CustomizedSqlInjector extends DefaultSqlInjector {
    /**
     * 如果只需增加方法,保留mybatis plus自帶方法,
     * 可以先獲取super.getMethodList(),再添加add
     */
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        methodList.add(new InsertBatchMethod());
        methodList.add(new UpdateBatchMethod());
        methodList.add(new MysqlInsertOrUpdateBath());
        return methodList;
    }
}

(4)在自己想使用的mapper上繼承自定義的mapper.

import com.sy.adp.common.mybatisPlusExtend.RootMapper;
import com.sy.adp.flowfull.entity.InfMpmPds;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;
 
@Component
public interface InfMpmPdsMapper extends RootMapper<InfMpmPds> {
 
    IPage<InfMpmPds> selectPageList(Page page, @Param("infMpmPds") InfMpmPds infMpmPds);
 
}

(5)在controller或serviceImpi中引入mapper,使用自定義的方法。

>>>>>>>>>>>>>>>>>>>>引入mapper>>>>>>>>>>>>>>>

>>>>>>>>>>>>>>>>>>>>>>>>>方法使用>>>>>>>>>>>>

完成上述步驟,就可以運(yùn)行項(xiàng)目進(jìn)行測試看看,數(shù)據(jù)提升是不是幾個數(shù)量級。

到此這篇關(guān)于mybatis-plus 關(guān)于savebatch,saveorupdatebatch遇到的坑及解決辦法的文章就介紹到這了,更多相關(guān)mybatis-plus savebatch,saveorupdatebatch內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot啟動時運(yùn)行代碼詳解

    springboot啟動時運(yùn)行代碼詳解

    在本篇內(nèi)容中我們給大家整理了關(guān)于在springboot啟動時運(yùn)行代碼的詳細(xì)圖文步驟以及需要注意的地方講解,有興趣的朋友們學(xué)習(xí)下。
    2019-06-06
  • SpringBoot如何獲取當(dāng)前操作用戶的id/信息

    SpringBoot如何獲取當(dāng)前操作用戶的id/信息

    在一般性的基設(shè)需求中,有需要獲取當(dāng)前用戶操作記錄的情況,也就是說我們需要記錄當(dāng)前用戶的信息,如:id、昵稱、賬號等信息,這篇文章主要介紹了SpringBoot獲取當(dāng)前操作用戶的id/信息,需要的朋友可以參考下
    2023-10-10
  • Java之常用類小結(jié)案例講解

    Java之常用類小結(jié)案例講解

    這篇文章主要介紹了Java之常用類小結(jié)案例講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • Spring?Boot配置文件的語法規(guī)則詳解(properties和yml)

    Spring?Boot配置文件的語法規(guī)則詳解(properties和yml)

    這篇文章主要介紹了Spring?Boot配置文件的語法規(guī)則,主要介紹兩種配置文件的語法和格式,properties和yml,對于配置文件也有獨(dú)立的文件夾存放,主要用來存放一些需要經(jīng)過變動的數(shù)據(jù)(變量值),感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • Java編譯器用maven打war包出錯解決辦法

    Java編譯器用maven打war包出錯解決辦法

    這篇文章主要介紹了用maven打war包出錯的解決辦法,需要的朋友可以參考下
    2018-03-03
  • 解讀maven項(xiàng)目啟動tomcat不報(bào)錯但是啟動不起來,tomcat啟動到警告log4j就停止了

    解讀maven項(xiàng)目啟動tomcat不報(bào)錯但是啟動不起來,tomcat啟動到警告log4j就停止了

    這篇文章主要介紹了maven項(xiàng)目啟動tomcat不報(bào)錯但是啟動不起來,tomcat啟動到警告log4j就停止了問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 冒泡排序的原理及java代碼實(shí)現(xiàn)

    冒泡排序的原理及java代碼實(shí)現(xiàn)

    冒泡排序法:關(guān)鍵字較小的記錄好比氣泡逐趟上浮,關(guān)鍵字較大的記錄好比石塊下沉,每趟有一塊最大的石塊沉底。算法本質(zhì):(最大值是關(guān)鍵點(diǎn),肯定放到最后了,如此循環(huán))每次都從第一位向后滾動比較,使最大值沉底,最小值上升一次,最后一位向前推進(jìn)
    2016-02-02
  • Java 中HttpURLConnection附件上傳的實(shí)例詳解

    Java 中HttpURLConnection附件上傳的實(shí)例詳解

    這篇文章主要介紹了Java 中HttpURLConnection附件上傳的實(shí)例詳解的相關(guān)資料,希望通過本文大家能掌握這樣的知識內(nèi)容,需要的朋友可以參考下
    2017-09-09
  • Java多線程三種主要實(shí)現(xiàn)方式解析

    Java多線程三種主要實(shí)現(xiàn)方式解析

    這篇文章主要介紹了Java多線程三種主要實(shí)現(xiàn)方式解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • Java實(shí)題演練二叉搜索樹與雙向鏈表分析

    Java實(shí)題演練二叉搜索樹與雙向鏈表分析

    這篇文章主要介紹了Java二叉搜索樹與雙向鏈表,總的來說這并不是一道難題,那為什么要拿出這道題介紹?拿出這道題真正想要傳達(dá)的是解題的思路,以及不斷優(yōu)化探尋最優(yōu)解的過程。希望通過這道題能給你帶來一種解題優(yōu)化的思路
    2022-12-12

最新評論