开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情
前言
总所周知,MyBatis-Plus 是一个 MyBatis的增强工具,只做增强不做改变,提供了很多通用的CRUD方法。
例如Service接口就提供了一个SaveBatch方法为我们提供批量插入,可能有人认为该方法就是会执行如下SQL语句
INSERT INTO table(id,name) VALUEs(1,"Tom"),(1,"Tom"),(1,"Tom")...
但如果你有留意MyBatis-Plus的DEBUG输出日志或者看过该方法的源码就知道,实际上还是一条条循环插入的。
源码
// ServiceImpl.java
@Transactional(
rollbackFor = {Exception.class}
)
public boolean saveBatch(Collection<T> entityList, int batchSize) {
String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE);
return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {
sqlSession.insert(sqlStatement, entity);
});
}
内部实际上就是不断遍历entityList这个集合来实现“批量插入”这个功能,那为啥不提供真正的批量插入的功能呢?
根据作者的说法,这是由于不同数据库对于批量插入支持度不同的问题,那么如果我们要实现真正的批量插入有什么办法吗?
解决方法
手动拼接SQL
最显眼的办法无非就是自己进行SQL拼接,但这样工作量有点太大了,当一个表的字段过多时,还容易出现拼接问题。
官方内置方法(MySQL)
其实官方是提供了真正的批量插入方法,但目前只在MySQL数据库上进行测试过,如果我们的项目使用的数据库恰好是MySQL的话就可以配置该可选项。
首先创建一个SQL注入器配置类
@Component
public class SpiceSqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList( mapperClass, tableInfo );
methodList.add( new InsertBatchSomeColumn() ); // 添加批量插入方法
return methodList;
}
}
随后我们定义一个扩展BaseMapper的接口,例如下面的例子:
public interface SpiceBaseMapper<T> extends BaseMapper<T> {
int insertBatchSomeColumn(List<T> entityList);
}
随后我们业务Mapper都需继承该SpiceBaseMapper接口,随后我们就可以正常调用该insertBatchSomeColumn方法了,通过日志的输出可以看到确实是真正的批量插入啦~