首页 > 其他分享 >mybatis-plus 批量插入/新增

mybatis-plus 批量插入/新增

时间:2023-06-01 10:13:16浏览次数:29  
标签:tableInfo String 批量 rewriteSqlDO stopWatch plus mybatis new append

建表

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for rewrite_sql
-- ----------------------------
DROP TABLE IF EXISTS `rewrite_sql`;
CREATE TABLE `rewrite_sql`  (
  `id` int NOT NULL DEFAULT -1,
  `stu_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `age` int NULL DEFAULT -1,
  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

 

搭建项目

server.port=1222

#数据库
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3308/mysql?useSSL=false&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root

#nocas
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

#mapper
mybatis.mapper-locations=classpath:mapper/*.xml

#日志输出
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

 

@Data
@TableName("rewrite_sql")
public class RewriteSqlDO implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.INPUT)
    private Integer id;

    private String stuName;

    private Integer age;

    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Date createTime;
}

 

 1、一条条插入

@Test
    void test() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        for (int i = 10000; i < 20000; i++) {        //测试1w条数据耗时
            RewriteSqlDO rewriteSqlDO = new RewriteSqlDO();
            rewriteSqlDO.setId(i);
            rewriteSqlDO.setAge(i);
            rewriteSqlDO.setStuName(String.valueOf(1));
            rewriteSqlMapper.insert(rewriteSqlDO);
        }
        stopWatch.stop();
        System.out.println(stopWatch.getLastTaskTimeMillis());
    }

 【注】

优点:
1.spring自带工具类,可直接使用且简单
2.性能消耗小,展示清晰,start和stop之间时间的误差更小

缺点:

一个stopWatch只能开启一个task,必须在stop之后才能开启新的,如果需要开启多个,则需要创建多个stopWatch实例

 结果耗时:

 

2、使用foreach

public interface RewriteSqlMapper extends BaseMapper<RewriteSqlDO> {            //注意:这里用的是BaseMapper
    int insertBatch(@Param("list") List<RewriteSqlDO> list);
}
    <insert id="insertBatch" parameterType="java.util.List">
        insert into rewrite_sql(id, stu_name, age, create_time) values
        <foreach collection="list" item="item" separator=",">
            (#{item.id}, #{item.stuName}, #{item.age}, #{item.createTime})
        </foreach>
    </insert>

 在配置文件数据库配置中加入:&rewriteBatchedStatements=true

@Test
void test1() {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    List<RewriteSqlDO> rewriteSqlDOList = new ArrayList<RewriteSqlDO>();
    for (int i = 1; i < 10000; i++) {
        RewriteSqlDO rewriteSqlDO = new RewriteSqlDO();
        rewriteSqlDO.setId(i);
        rewriteSqlDO.setAge(i);
        rewriteSqlDO.setStuName(String.valueOf(i));
        rewriteSqlDOList.add(rewriteSqlDO);
    }
    rewriteSqlMapper.insertBatch(rewriteSqlDOList);
    stopWatch.stop();
    System.out.println(stopWatch.getLastTaskTimeMillis());
}

结果耗时:

 

 3、自定义插入/更新

简述就是,封装好的foreach方法,性能耗时与第二种接近

public interface CommonMapper<T> extends BaseMapper<T> {

    /**
     * 自定义批量插入
     * 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
     */
    int insertBatch(@Param("list") List<T> list);

    /**
     * 自定义批量更新,条件为主键
     * 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
     */
    int updateBatch(@Param("list") List<T> list);
    
}
/**
 * 批量新增
 */
@Slf4j
public class InsertBatchMethod extends AbstractMethod {

    @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);
        // 第三个参数必须和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 -> {
            //新增时修改字段不填充
            if (!("update_time".equals(x.getColumn()))
                    &&!("update_user_id".equals(x.getColumn()))
                    &&!("update_user_name".equals(x.getColumn()))){
                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 -> {
            if (!("updateTime".equals(x.getProperty()))
                    &&!("updateUserId".equals(x.getProperty()))
                    &&!("updateUserName".equals(x.getProperty()))){
                valueSql.append("#{item.").append(x.getProperty()).append("},");
            }
        });
        valueSql.delete(valueSql.length() - 1, valueSql.length());
        valueSql.append("</foreach>");
        return valueSql.toString();
    }
}
/**
 * 批量更新方法实现,条件为主键,选择性更新
 */
@Slf4j
public class UpdateBatchMethod extends AbstractMethod {

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sql = "<script>\n<foreach collection=\"list\" item=\"item\" separator=\";\">\nupdate %s %s where %s=#{%s} %s\n</foreach>\n</script>";
        String additional = tableInfo.isWithVersion() ? tableInfo.getVersionFieldInfo().getVersionOli("item", "item.") : "" + tableInfo.getLogicDeleteSql(true, true);
        String setSql = sqlSet(tableInfo.isWithLogicDelete(), false, tableInfo, false, "item", "item.");
        String sqlResult = String.format(sql, tableInfo.getTableName(), setSql, tableInfo.getKeyColumn(), "item." + tableInfo.getKeyProperty(), additional);
        log.debug("sqlResult----->{}", sqlResult);
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
        // 第三个参数必须和RootMapper的自定义方法名一致
        return this.addUpdateMappedStatement(mapperClass, modelClass, "updateBatch", sqlSource);
    }
  
}

 

@Slf4j
public class MyInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
//        log.info("==============methodList===================");
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        methodList.add(new InsertBatchMethod());
        methodList.add(new UpdateBatchMethod());
        return methodList;
    }

}
@Slf4j
@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
//        log.info("===================mybatisPlusInterceptor====================");
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }


    @Bean
    public MyInjector myInjector(){
//        log.info("========================myInjector===================================");
        return new MyInjector();
    }

}

 

@Test
void test2() {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    List<RewriteSqlDO> rewriteSqlDOList = new ArrayList<RewriteSqlDO>();
    for (int i = 100000; i < 200000; i++) {
        RewriteSqlDO rewriteSqlDO = new RewriteSqlDO();
        rewriteSqlDO.setId(i);
        rewriteSqlDO.setAge(i);
        rewriteSqlDO.setStuName(String.valueOf(i));
        rewriteSqlDOList.add(rewriteSqlDO);
    }
    rewriteSqlMapper.insertBatch(rewriteSqlDOList);
    stopWatch.stop();
    System.out.println(stopWatch.getLastTaskTimeMillis());
}

 【注意】

 在配置文件数据库配置中加入:&allowMultiQueries=true

 

 结果耗时:

 

标签:tableInfo,String,批量,rewriteSqlDO,stopWatch,plus,mybatis,new,append
From: https://www.cnblogs.com/shirleyxueli/p/17448142.html

相关文章

  • MyBatis之执行器(Excutor)
    MyBatis之执行器(Executor)前面的文章已经介绍了MyBatis的基本使用流程,但我们不能仅仅局限于使用,而是应该去横向扩展,往更深的方向研究。今天就先讲解一下MyBatis中的执行器Executor。我们在CURD的时候,每次都会去获取一个新的SqlSession对象,可以看出来这个接口主要定义类关于CRUD......
  • mybatis
    MyBatis的基本使用MyBatis类中编写://1、加载mybatis的核心配置文件,获取SqlSessionFactoryStringresource="mybatis-config.xml";InputStreaminputStream=Resources.getResourceAsStream(resource);SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().......
  • neo4j,python,批量建立节点时,会重复建立相同名称节点。去重。
    前提经过度娘得知,可以使用第三方包去重,但只管去重,你后面关系乱了人家第三方包不管。=-=或者直接在neo4j里面使用数据库语言去重,但关系还是得重新建立。况且,我想用python去重。干货来了后来,我换了个思路,那么就是合并节点。(虽然跟去重差不多)但总归总做出来了使用NodeMatcher......
  • 解决mybatis-plus查询字段中含有关键词时异常问题
    在使用mybatis-plus查询mysql某张表的数据时,一直告警提示sqlsyntaxerror。于是,把异常提示里的sql语句复制到navicat执行,也提示sqlsyntaxerror。仔细看了下,发有几个字段在navigate里面标示为蓝色(这几个字段为sensitive、status、name),这几个字段在mysql里面是关键词。在查询语......
  • 使用脚本批量Telnet和Curl测试端口是否连通
    使用脚本批量Telnet测试端口是否连通,使用telnet:telnets.sh:#!/bin/bashcheck_telnet(){forip_portin$(catip_info|grep-v'^#')doCHECK_PORT=$(echo$ip_port|awk-F:'{print$2}')CHECK_IP=$(echo$ip_port|awk-F:'{print$1}')......
  • MyBatis+Sharding-JDBC实体类LocalDateTime类型字段查询报SQLFeatureNotSupportedExce
    问题最近协助渠道组开发新需求,封装实现了一个公共模块供不同渠道项目使用。以前各个渠道项目有很多相似的菜单和功能,各自项目里自己的代码实现,本公共模块对新需求的功能点进行抽象,减少重复代码,提高模块复用性和可维护性。目前有2个渠道项目接入了该公共模块,自测时发现其中1个运......
  • Mybatis Plus
    MyBatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率1.MyBatisPlus简介入门案例MyBatisPlus概述2.标准数据层开发标准数据层CRUD功能分页功能3.DQL控制条件查询方式查询投影查询条件设定字段映射与表名映射4.DML控制id自增......
  • 使用OnePlus 6T(一加6T)刷入 Kali NetHunter的操作总结
    前景概述:看到网上有人用手机进行BadUSB攻击,自己也幻想了一下在手机中使用KaliLinux的场景,看到Kali官方提供的有移动端的设备Nethunter,于是我就筹划这准备刷入这个系统。想要刷入NetHunter,并不是非常简单的事情,但是如果你有刷机基础的话,也可以是很简单的步骤。我是一个小白,一......
  • Mybatis-plus关于代码生成器的使用
    1、添加依赖 2、在test包下创建一个CodeGet类,实现生成代码的功能。注意:全局配置、数据源配置一定要和自己的电脑配置一致! 3、执行CodeGet类中的main方法。打印台有如下图提示字样,即自动生成成功。 4、对比两张图。在wechat文件夹下有controller、entity、mapper、s......
  • 创龙教仪TL6748-PlusTEB教学实验箱实验操作教程:2-2 LED灯控制实验
    2-2LED灯控制实验(点击查看完整视频)1、实验目的本次视频教程是基于创龙教仪TL6748-PlusTEB教学实验箱完成的。本节视频的目的是学习基于StarterWare开发环境配置GPIO管脚的方法和原理,并实现StarterWare开发环境下的LED灯控制。2、实验原理StarterWareStarterWare是一个免费的软件开......