mybatisPlus批量保存报错 : java.sql.SQLException: does not support insert multiple rows in one sql statement
用的BatchInsert逐行插入的?
mybatisPlus的插入可以直接saveBatch插入一个list集合
针对mybatisPlus批量保存数据时出现"不支持在一条sql语句中插入多行"错误,可以采用以下两种方案解决:
BatchExecutor
进行批量操作。示例代码如下:List<T> entityList = new ArrayList<>(); //准备的需要批量保存的实体类List
SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH);
try{
for(int i = 0; i < entityList.size(); i++){
sqlSession.insert(entityName + "_mapper.insert", entityList.get(i));
if(i % batchSize == 0){
sqlSession.flushStatements();
sqlSession.clearCache();
}
}
sqlSession.flushStatements();
sqlSession.commit();
}finally{
sqlSession.close();
}
BatchInsertMapper
并在mybatisPlus配置文件中注入该mapper。在该mapper中利用foreach
循环进行批量操作,以达到不在一条sql语句中插入多行的效果。示例代码如下:public interface BatchInsertMapper<T> extends BaseMapper<T> {
/**
* 批量插入方法
*
* @param list 批量插入的List
* @return 插入的条数
*/
@InsertProvider(type = BatchInsertProvider.class, method = "dynamicSQL")
int batchInsert(List<T> list);
}
public class BatchInsertProvider extends SqlProviderSupport {
public String batchInsert(Map<?, ?> map) {
List<?> list = (List<?>) map.get("list");
if (CollectionUtils.isEmpty(list)) {
throw new RuntimeException("batch insert list is empty!");
}
Class<?> clazz = list.get(0).getClass();
String tableName = getTableName(clazz);
StringBuilder sql = new StringBuilder();
sql.append("INSERT INTO ").append(tableName).append(" (");
List<String> columns = getColumns(clazz, false);
sql.append(CollUtil.join(columns, ","));
sql.append(") VALUES ");
String foreachSql = "list[" + map.get("index") + "]";
sql.append("<foreach collection=\"").append(foreachSql).append("\" item=\"i\" index=\"index\" separator=\",\">(");
for (int i = 0; i < columns.size(); i++) {
sql.append("#{i.").append(columns.get(i)).append("},");
}
sql.deleteCharAt(sql.lastIndexOf(","));
sql.append(")</foreach>");
return sql.toString();
}
}
在mybatisPlus配置文件中注入BatchInsertMapper:
@Bean
public BatchInsertMapper batchInsertMapper() {
return new BatchInsertMapper() {};
}
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor()); //多租户插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); //乐观锁插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); //分页插件
return interceptor;
}
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setPlugins(mybatisPlusInterceptor());
factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/**/*.xml"));
factoryBean.setTypeHandlers(new TypeHandler<?>[]{new MybatisLongEnumTypeHandler<>()});
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setBanner(false);
globalConfig.setMetaObjectHandler(new MyMetaObjectHandler());
factoryBean.setGlobalConfig(globalConfig);
return factoryBean.getObject();
}