项目基于优秀开源项目:若依
项目背景:项目中牵扯到数据批量导入,为提高性能,先考虑将MybatisPlus伪批量插入增强为真实批量插入
MybatisPlus源码:
MybatisPlus支持批量插入,但是跟踪源码发现底层是将批量插入的数据循环执行了N次单条插入:
IService源码:
java
@Transactional(
rollbackFor = {Exception.class}
)
default boolean saveBatch(Collection<T> entityList) {
return this.saveBatch(entityList, 1000);
}
boolean saveBatch(Collection<T> entityList, int batchSize);
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);
});
}
底层支持增强改造:
1、创建自定义sql注入类:MySqlInjector.java
java
public class MySqlInjector extends DefaultSqlInjector {
public MySqlInjector() {
}
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
methodList.add(new InsertBatchSomeColumn(i -> i.getFieldFill() != FieldFill.UPDATE));
return methodList;
}
}
2、创建自定义Mapper MyBaseMapper.java
java
public interface MyBaseMapper<T> extends BaseMapper<T> {
/**
* 批量插入 仅适用于mysql
*
* @param entityList 实体列表
* @return 影响行数
*/
Integer insertBatchSomeColumn(Collection<T> entityList);
}
3、业务Mapper实现自定义的Mapper
java
@Repository
public interface TestMapper extends MyBaseMapper<Test>
{
}
4、业务中批量插入,使用insertBatchSomeColumn函数
java
insertBatchSomeColumn(list);
5、新建MyBatisPlus配置类,将自定义sql注入 MybatisPlusConfig.java
java
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//指定使用数据库类型
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean
public DefaultSqlInjector mySqlInjector() {
return new MySqlInjector();
}
}
在使用默认MybatisPlus配置默认 sessionFactory时,以上即可
此处基于若依,需要将自定义sessionFactory设置为自定义sql注入器
配置文件位置,参考
framwork模块下config包MyBatisConfig
java
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception
{
String typeAliasesPackage = env.getProperty("mybatis.typeAliasesPackage");
String mapperLocations = env.getProperty("mybatis.mapperLocations");
String configLocation = env.getProperty("mybatis.configLocation");
typeAliasesPackage = setTypeAliasesPackage(typeAliasesPackage);
VFS.addImplClass(SpringBootVFS.class);
final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
sessionFactory.setDataSource(dataSource);
sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
sessionFactory.setMapperLocations(resolveMapperLocations(StringUtils.split(mapperLocations, ",")));
sessionFactory.setConfigLocation(new DefaultResourceLoader().getResource(configLocation));
//自定义批量插入
GlobalConfig globalConfig = new GlobalConfig();
GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
globalConfig.setDbConfig(dbConfig);
globalConfig.setSqlInjector(new MySqlInjector());
sessionFactory.setGlobalConfig(globalConfig);
return sessionFactory.getObject();
}
基于以上,大功告成。快去试试效果吧