【Java】MyBatis 批量插入資料,以及效能測試
阿新 • • 發佈:2022-03-07
測試環境
Java 1.8 ,spring boot 2.6.4具體依賴如下
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
Mapper.xml配置
<insert id="saveBatchCustom">
insert into user
(name,password,createtime)
values
<foreach collection="list" item="item" separator=",">
(#{item.name},#{item.password},#{item.createTime})
</foreach>
</insert>
UserMapper.java
@Mapper public interface UserMapper extends BaseMapper<UserPO> { boolean saveBatchCustom(List<UserPO> list); }
UserService.java
@Service public class UserService extends ServiceImpl<UserMapper, UserPO> { @Autowired private UserMapper userMapper; @Autowired private JdbcTemplate jdbcTemplate; @Transactional public boolean saveBatchCustom(List<UserPO> list) { return userMapper.saveBatchCustom(list); } @Transactional public void jdbcBatchInsert(List<UserPO> list, final int batchSize) { String sql = "insert into user (name,password,createtime) values(?,?,?)"; jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { @Override public void setValues(PreparedStatement ps, int i) throws SQLException { UserPO userPO = list.get(i); ps.setString(1, userPO.getName()); ps.setString(2, userPO.getPassword()); ps.setDate(3, new Date(userPO.getCreateTime().getTime())); } @Override public int getBatchSize() { return batchSize < 1 ? 1000 : batchSize; } }); } }
測試類
@SpringBootTest
public class BatchInsertDataTest {
private Logger logger = LoggerFactory.getLogger(getClass());
private static final int MAXCOUNT = 10000;
@Autowired
private UserMapper userMapper;
@Autowired
private UserService userService;
@BeforeEach
public void atest1() {
Wrapper<UserPO> query = new QueryWrapper<UserPO>();
userMapper.delete(query);
logger.info("清空資料表");
}
@Test
public void mybatisForeach() {
StopWatch sw = new StopWatch("testBatchInsert2");
sw.start();
List<UserPO> list = new ArrayList<>();
UserPO user = null;
for (int i = 0; i < MAXCOUNT; i++) {
user = new UserPO();
user.setName("test" + i);
user.setPassword("p" + i);
list.add(user);
}
userService.saveBatchCustom(list);
sw.stop();
logger.info("saveBatchCustom:{}", sw.getTotalTimeMillis());
}
@Test
public void mybatisPlusBatchSave() {
StopWatch sw = new StopWatch("mybatisPlusBatchSave");
sw.start();
List<UserPO> list = new ArrayList<>();
UserPO user = null;
for (int i = 0; i < MAXCOUNT; i++) {
user = new UserPO();
user.setName("test" + i);
user.setPassword("p" + i);
list.add(user);
}
userService.saveBatch(list, 500);
sw.stop();
logger.info("mybatisPlusBatchSave:{}", sw.getTotalTimeMillis());
}
@Test
public void jdbcBatchSave() {
StopWatch sw = new StopWatch("jdbcBatchSave");
sw.start();
List<UserPO> list = new ArrayList<>();
UserPO user = null;
for (int i = 0; i < MAXCOUNT; i++) {
user = new UserPO();
user.setName("test" + i);
user.setPassword("p" + i);
user.setCreateTime(new Date());
list.add(user);
}
userService.jdbcBatchInsert(list, 500);
sw.stop();
logger.info("jdbcBatchSave:{}", sw.getTotalTimeMillis());
}
}
測試結果
在個人電腦上測試了一個大體範圍。具體可能因環境而異,不會有太大差距
- 資料量大於1000
jdbcBatchSave > mybatisPlusBatchSave >mybatisForeach並隨著資料量越大差距越大。 - 小於1000大於300
jdbcBatchSave > mybatisPlusBatchSave >mybatisForeach 之間效能差距在縮小,mybatisPlusBatchSave與mybatisForeach每次測試資料不固定, - 小於 300
推薦使用mybatisPlusBatchSave,