mybatis-plus实现批量插入

434 阅读2分钟

1. 项目结构

image.png

1.1 创建实体类

/**  
 * @author ml  
 * @date 2023年05月06日 22:44  
 */@EqualsAndHashCode(callSuper = true)  
@Data  
public class Demo extends BaseEntity {  
  
    private static final long serialVersionUID = -322957748844213757L;  
    /**  
     * 姓名     */    private String name;  
    /**  
     * 年龄     */    private Integer age;  
    /**  
     * 性别     */    private Integer gender;  
  
}

1.2 创建controller

/**  
 * @author ml  
 * @date 2023年05月06日 22:42  
 */@RestController  
@RequestMapping("/papi/dome")  
public class DemoController {  
  
    @Resource  
    private DemoService demoService;  
  
}

1.3 创建service

1. 创建baseservice
2. 创建baseServiceImpl
3. 创建DemoService
4. 创建DemoServiceImpl
public interface BaseService<Entity extends BaseEntity> extends IService<Entity> {  
  
}
 
public class BaseServiceImpl<M extends BaseMapper<T>, T extends BaseEntity> extends ServiceImpl<M, T> implements BaseService<T> {  

}

public interface DemoService extends BaseService<Demo> {  
}

@Transactional  
@Service  
public class DemoServiceImpl extends BaseServiceImpl<DemoDao, Demo> implements DemoService {  
  
}

1.4 创建dao

@Mapper  
public interface DemoDao extends BaseDao<Demo> {  
  
}

<?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.ml.finance.demo.DemoDao">  
  
  
</mapper>

1.5 创建数据库

create table demo  
(  
    `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',  
  `name` varchar(30) NOT NULL DEFAULT '' COMMENT '姓名',  
  `age` int(11) NULL DEFAULT NULL COMMENT '年龄',  
  `gender` tinyint(2) NOT NULL DEFAULT 0 COMMENT '性别,0:女 1:男',  
  PRIMARY KEY (`id`)  
)  
    charset = utf8;

2. mybatis-plus自带批量插入

2.1 在controller中新增代码

@RequestMapping("/test")  
public void test() {  
    List<Demo> list = new ArrayList<>();  
    for (int i = 0; i < 1000; i++) {  
        Demo demo = new Demo();  
        demo.setName(i+"");  
        list.add(demo);  
    }  
    demoService.saveBatch(list);  
}

2.1 结果

Pasted image 20230506234051.png

但是在真正的业务中,发现此批量新增的方法还是执行了单条插入的逻辑,只不过mybatisPlus对部分连接做了优化,性能还是比for循环快很多

Pasted image 20230506234438.png

3. 利用 SQL 注入器实现真的批量插入

3.1 创建一个 SQL 注入器 InsertBatchSqlInjector

/**  
 * SQL 注入器 * @author ml  
 * @date 2023年05月06日 23:46  
 */public class InsertBatchSqlInjector extends DefaultSqlInjector {  
    @Override  
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {  
        // super.getMethodList() 保留 Mybatis Plus 自带的方法  
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);  
        // 添加自定义方法:批量插入,方法名为 insertBatchSomeColumn  
        methodList.add(new InsertBatchSomeColumn());  
        return methodList;  
    }  
}

3.2 说说 InsertBatchSomeColumn

InsertBatchSomeColumn 是 Mybatis Plus 内部提供的默认批量插入,只不过这个方法作者只在 MySQL 数据测试过,所以没有将它作为通用方法供外部调用,注意看注释:

Pasted image 20230506235129.png

3.3 配置 SQL 注入器

/** * 自定义批量插入 SQL 注入器 */ 
@Bean 
public InsertBatchSqlInjector insertBatchSqlInjector() { 
	return new InsertBatchSqlInjector(); 
}

注意:方法名必须为 insertBatchSomeColumn, 和 InsertBatchSomeColumn 内部定义好的方法名保持一致。

3.4 测试

	@Transactional(rollbackFor = Exception.class)  
    @Override  
    public void gradJiSiLuData() throws Exception {  
        JslDataInfo instance = JslDataInfo.getInstance();  
        List<Kzz> list = instance.listKzz(true);  
        if (ObjectUtil.isNotEmpty(list)) {  
            kzzDao.truncateTable();  
            //mybatis plus 自带批量插入  
//            this.saveBatch(list);  
            //自定义方法插入,执行分片插入            
            List<List<Kzz>> partition = ListUtil.partition(list, 100);  
            for (List<Kzz> kzzList : partition) {  
                kzzDao.insertBatchSomeColumn(kzzList);  
            }  
        }  
    }
  • 成功批量插入

Pasted image 20230507000254.png