mybatis-plus的 IService接口 默认提供 saveBatch批量插入,也是唯一一个默认批量插入,在数据量不是很大的情况下可以直接使用,但这种是一条一条执行的效率上会有一定的瓶颈,今天我们就来研究研究mybatis-plus中的批量插入。
1. 准备测试环境
新建一个测试表,用插入5000条数据来测试
CREATE TABLE `users` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `user_name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, `email` varchar(255) DEFAULT NULL, `address` varchar(255) DEFAULT NULL, `account` varchar(255) DEFAULT NULL, `password` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=60204 DEFAULT CHARSET=utf8;
pom依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.7.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.7.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.13</version> </dependency> </dependencies>
yml配置
spring: application: name: example-server datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/my_user?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai username: root password: root main: allow-circular-references: true mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启SQL语句打印
实体类
/** * @description: 默认驼峰转换 * @author: yh * @date: 2022/8/29 */ @Data public class Users extends Model<Users> { /** * id自增 */ @TableId(value = "id", type = IdType.AUTO) private Long id; private LocalDateTime createTime; private String userName; private Integer age; private String email; private String address; private String account; private String password; }
UsersMapper
public interface UsersMapper extends BaseMapper<Users> { }
UsersMapper.xml
<?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.mapper.UsersMapper"> </mapper>
service接口
public interface UsersService extends IService<Users> { }
service实现
@Service public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements UsersService { }
配置扫描
@MapperScan("com.example.mapper") @SpringBootApplication public class SpringExampleApplication { public static void main(String[] args) { SpringApplication.run(SpringExampleApplication.class, args); } }
环境准备完成。
2. saveBatch
@RequestMapping(value = "/api") @RestController @Slf4j public class ExampleController { @Autowired private UsersService usersService; @RequestMapping(value = "/load", method = RequestMethod.GET) public void load() { List<Users> list = new ArrayList<>(); for (int i = 0; i < 5000; i++) { Users users = new Users(); users.setUserName("yy" + i); users.setAge(18); users.setEmail("123@qq.com"); users.setAddress("临汾" + i); users.setAccount("account" + i); users.setPassword("password" + i); list.add(users); } long start = System.currentTimeMillis(); usersService.saveBatch(list); long end = System.currentTimeMillis(); System.out.println("5000条数据插入,耗时:" + (end - start)); } }
执行过程:
5000条数据被分成了5次执行,每次1000条,整体是一个事务
耗时:48.5秒
2.1 分析
点进saveBatch方法,看看内部是怎么实现的
注意看,方法有一个事务注解,说明插入整批数据会作为一个事务进行
默认1000条一次,怪不得执行时每隔1000条会处于一个准备执行状态,等待几秒后才会往下执行(这里等待的时间就是1000个单条的insert语句执行的时间)
再往下点是一个saveBatch接口,参数分别是插入的对象集合、插入批次数量也就是默认的1000
查看它的实现类
这里也有一个事务的注解,这是因为saveBatch是一个重载方法,插入的时候也可以指定插入批次数量调用
继续往下进入executeBatch