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

mybatis-plus批量插入優(yōu)化方式

 更新時(shí)間:2024年09月25日 15:48:49   作者:hogenlaw  
MyBatis-Plus的saveBatch()方法默認(rèn)是單條插入,通過(guò)在JDBC URL添加rewriteBatchedStatements=true參數(shù)啟用批量插入,官方提供的sql注入器可自定義方法,如InsertBatchSomeColumn實(shí)現(xiàn)真批量插入,但存在單次插入數(shù)據(jù)量過(guò)大問(wèn)題,可通過(guò)分批插入優(yōu)化,避免超出MySQL限制

mybatis-plus批量插入優(yōu)化

背景

使用的mybatisplus的批量插入方法:

saveBatch(),打印 sql 日志發(fā)現(xiàn),底層還是一條條的 insert 語(yǔ)句,這顯然是不行的

優(yōu)化

之前就看到過(guò)網(wǎng)上都在說(shuō)在jdbc的url路徑上加上rewriteBatchedStatements=true 參數(shù)mysql底層才能開啟真正的批量插入模式。但是我已經(jīng)添加了

通過(guò)查閱相關(guān)文檔后,發(fā)現(xiàn)mybatisPlus提供了sql注入器,我們可以自定義方法來(lái)滿足業(yè)務(wù)的實(shí)際開發(fā)需求。

sql 注入器官網(wǎng):https://baomidou.com/guides/sql-injector/

mybatis-plus -core 核心包提供了基本的增刪查改注入器,在批量插入數(shù)據(jù)這里顯然不夠,所以可以看到在 mybaits-plus-extension 包下還額外提供了批量插入的可注入方法


  • AlwaysUpdateSomeColumnById: 根據(jù)Id更新每一個(gè)字段,全量更新不忽略null字段,解決mybatis-plus中updateById默認(rèn)會(huì)自動(dòng)忽略實(shí)體中null值字段不去更新的問(wèn)題;
  • InsertBatchSomeColumn: 真實(shí)批量插入,通過(guò)單SQL的insert語(yǔ)句實(shí)現(xiàn)批量插入;
  • Upsert:更新or插入,根據(jù)唯一約束判斷是執(zhí)行更新還是刪除,相當(dāng)于提供insert on duplicate key update支持。

我們只需要把這個(gè)方法添加進(jìn)我們的sql注入器即可。

config包新增如下兩個(gè)配置

public class MySqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        //更新時(shí)自動(dòng)填充的字段,不用插入值
        methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
        return methodList;
    }
}
@Configuration
public class MybatisPlusConfig {
    @Bean
    public MySqlInjector sqlInjector() {
        return new MySqlInjector();
    }
}

原先的 mapper 是這么寫的

public interface UserMapper extends BaseMapper<User> {
}

我們新增了 InsertBatchSomeColumn 方法,需要重新定義一個(gè) BaseMapper

public interface CommonMapper<T> extends BaseMapper<T> {
    /**
     * 真正的批量插入
     * @param entityList
     * @return
     */
    int insertBatchSomeColumn(List<T> entityList);
}
public interface UserMapper extends CommonMapper<User> {
}

優(yōu)化后的接口就對(duì)了,sql 顯示確實(shí)是 批量插入的語(yǔ)句

新的問(wèn)題

上面雖然實(shí)現(xiàn)了真正意義上的sql層面的批量插入。

但是,到這里并沒有結(jié)束,mybatisPlus官方提供的 insertBatchSomeColumn 方法不支持分批插入,也就是有多少直接全部一次性插入,這就可能會(huì)導(dǎo)致最后的 sql 拼接語(yǔ)句特別長(zhǎng),超出了mysql 的限制, 可能會(huì)報(bào)下面這個(gè)錯(cuò),

說(shuō)你這個(gè)包太大了??梢酝ㄟ^(guò)設(shè)置 max_allowed_packet 來(lái)改變包大小。

當(dāng)然我們可以通過(guò)下面的語(yǔ)句查詢當(dāng)前的配置大小:

select @@max_allowed_packet;

我這里就使用 sql 語(yǔ)句把值修改為 64M:

set global max_allowed_packet = 1024*1024*64;

但是改這個(gè)配置治標(biāo)不治本,能不能從代碼層面對(duì)拼接的 sql 語(yǔ)句做個(gè)優(yōu)化呢,限制不要太大,于是我們還要實(shí)現(xiàn)一個(gè)類似于saveBatch 分批的批量插入方法。

分批插入

模仿原來(lái)的saveBatch方法:

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean saveBatch(Collection<User> entityList, int batchSize) {
        try {
            int size = entityList.size();
            int idxLimit = Math.min(batchSize, size);
            int i = 1;
            //保存單批提交的數(shù)據(jù)集合
            List<User> oneBatchList = new ArrayList<>();
            for (Iterator<User> it = entityList.iterator(); it.hasNext(); ++i) {
                User element = it.next();
                oneBatchList.add(element);
                if (i == idxLimit) {
                    baseMapper.insertBatchSomeColumn(oneBatchList);
                    //每次提交后需要清空集合數(shù)據(jù)
                    oneBatchList.clear();
                    idxLimit = Math.min(idxLimit + batchSize, size);
                }
            }
        } catch (Exception e) {
            log.error("saveBatch fail", e);
            return false;
        }
        return true;
    }
}

從下面結(jié)果可以看到,最終的 sql 分成了兩個(gè)批次,這樣的話 sql 語(yǔ)句就不會(huì)太長(zhǎng)

springboot3整合mybaits-plus

這里就簡(jiǎn)單粘貼一下pom文件,注意 用mybatis-plus-spring-boot3-starter 這個(gè)依賴,不是用 mybatis-plus-spring-boot-starter ,不然報(bào)錯(cuò)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.3.0</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example.springbootV3</groupId>
	<artifactId>springbootV3</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springbootV3</name>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<version>3.1.3</version>
		</dependency>
		<dependency>
			<groupId>com.mysql</groupId>
			<artifactId>mysql-connector-j</artifactId>
		</dependency>
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
			<version>3.5.5</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>
spring.datasource.url=jdbc:mysql://192.168.133.128:3306/wxpay?useUnicode=true&characterEncoding=utf-8&rewriteBatchedStatements=true&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.mapper-locations=classpath:/com/example/demo/**/*Mapper.xml

mybatis 插入后返回主鍵

如果是使用了 mybatis-plus,可以直接使用封裝好的 insert 方法,通過(guò) service直接調(diào)用

userService.save(user);
Integer id = user.getId();

如果直接使用 mybatis,有下面兩種方法。

  • 一種是 在 insert 標(biāo)簽加入 useGeneratedKeys="true" keyProperty="id" 屬性,
  • 一種是 selectKey 標(biāo)簽
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <insert id="saveReturnPK1" parameterType="com.example.demo.entity.User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO `wxpay`.`t_user`(`name`, age) VALUES(#{name}, #{age})
    </insert>
    <insert id="saveReturnPK2" parameterType="com.example.demo.entity.User">
        <selectKey keyProperty="id" resultType="int" order="AFTER">
            SELECT LAST_INSERT_ID()
        </selectKey>
        INSERT INTO `wxpay`.`t_user`(`name`, age) VALUES(#{name}, #{age})
    </insert>
</mapper>
userMapper.saveReturnPK1(user);
Integer id = user.getId();

mybaits-plus 代碼生成器

mybatis-plus新版本通過(guò) builder 模式可以快速生成你想要的代碼,快速且優(yōu)雅,官網(wǎng)在這里

public class CodeGenerator {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://192.168.133.128:3306/wxpay", "root", "root")
                .globalConfig(builder -> {
                    builder.author("guang") // 設(shè)置作者
                            .enableSwagger() // 開啟 swagger 模式
                            .outputDir("D://MP//"); // 指定輸出目錄
                })
                .dataSourceConfig(builder ->
                        builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                            int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                            if (typeCode == Types.SMALLINT) {
                                // 自定義類型轉(zhuǎn)換
                                return DbColumnType.INTEGER;
                            }
                            return typeRegistry.getColumnType(metaInfo);
                        })
                )
                .packageConfig(builder ->
                        builder
                                .moduleName("com.example.demo") // 設(shè)置父包模塊名
                                .entity("entity")
                                .mapper("mapper")
                                .service("service")
                                .serviceImpl("service.impl")
                                .xml("mapper.xml")
                                .pathInfo(Collections.singletonMap(OutputFile.xml, "D://MP//")) // 設(shè)置mapperXml生成路徑
                )
                .strategyConfig(builder ->
                        builder.addInclude("t_user") // 設(shè)置需要生成的表名
                                .addTablePrefix("t_", "c_") // 設(shè)置過(guò)濾表前綴
                                .serviceBuilder().formatServiceFileName("%sService")
                )
                .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默認(rèn)的是Velocity引擎模板
                .execute();
    }
}

注意需要引入Freemarker 依賴,不然報(bào)錯(cuò)

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring中的兩種代理JDK和CGLIB的區(qū)別淺談

    Spring中的兩種代理JDK和CGLIB的區(qū)別淺談

    本篇文章中主要介紹了Spring中的兩種代理JDK和CGLIB的區(qū)別淺談,詳解的介紹了JDK和CGLIB的原理和方法,有需要的朋友可以了解一下
    2017-04-04
  • JAVA中使用JSON進(jìn)行數(shù)據(jù)傳遞示例

    JAVA中使用JSON進(jìn)行數(shù)據(jù)傳遞示例

    本篇文章主要介紹了JAVA中使用JSON進(jìn)行數(shù)據(jù)傳遞示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • ByteArrayInputStream簡(jiǎn)介和使用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    ByteArrayInputStream簡(jiǎn)介和使用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    ByteArrayInputStream 是字節(jié)數(shù)組輸入流。它繼承于InputStream。這篇文章主要介紹了ByteArrayInputStream簡(jiǎn)介和使用_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理,需要的朋友可以參考下
    2017-05-05
  • Java xml數(shù)據(jù)格式返回實(shí)現(xiàn)操作

    Java xml數(shù)據(jù)格式返回實(shí)現(xiàn)操作

    這篇文章主要介紹了Java xml數(shù)據(jù)格式返回實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • 詳解如何在React中逃離閉包陷阱

    詳解如何在React中逃離閉包陷阱

    眾所周知,JavaScript 中的閉包(Closures)一定是這種語(yǔ)言最可怕的特性之一,另外它可能也是最隱蔽的語(yǔ)言特性之一,我們?cè)诰帉?nbsp;React 代碼時(shí)經(jīng)常會(huì)用到它,但是大多數(shù)時(shí)候我們甚至沒有意識(shí)到這一點(diǎn),本文小編將和大家一起深入探討如何在React中逃離閉包陷阱
    2023-09-09
  • ScheduledThreadPoolExecutor巨坑解決

    ScheduledThreadPoolExecutor巨坑解決

    這篇文章主要為大家介紹了使用ScheduledThreadPoolExecutor遇到的巨坑解決示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Spring下Filter過(guò)濾器配置全局異常處理的詳細(xì)步驟

    Spring下Filter過(guò)濾器配置全局異常處理的詳細(xì)步驟

    這篇文章主要介紹了Spring下Filter過(guò)濾器配置全局異常處理的詳細(xì)步驟,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • 談?wù)凷pring 注入properties文件總結(jié)

    談?wù)凷pring 注入properties文件總結(jié)

    本篇談?wù)凷pring 注入properties文件總結(jié),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • Java設(shè)計(jì)模式之原型模式詳解

    Java設(shè)計(jì)模式之原型模式詳解

    這篇文章主要介紹了Java設(shè)計(jì)模式之原型模式詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • 詳解Gradle安裝并配置到IDEA的方法

    詳解Gradle安裝并配置到IDEA的方法

    這篇文章主要介紹了Gradle安裝并配置到IDEA的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09

最新評(píng)論

谷城县| 乌恰县| 崇义县| 临西县| 岗巴县| 喀什市| 南华县| 乌恰县| 长治县| 通道| 自贡市| 新沂市| 平遥县| 阿坝县| 溧阳市| 义乌市| 台南市| 大石桥市| 通辽市| 新乡县| 当雄县| 邯郸市| 枣庄市| 聂荣县| 灵山县| 石泉县| 南投县| 兖州市| 彰武县| 临朐县| 临汾市| 辽源市| 合作市| 伊吾县| 莎车县| 余干县| 西华县| 内乡县| 宁都县| 鱼台县| 平山县|