mybatis批量操作
一、mybatis批量操作
import org.apache.ibatis.session.SqlSession;
/**
* @Description 批量操作形式化参数接口
* @Author lcy
* @Date 2021/5/25 16:31
*/
public interface BatchOperationApi {
@Slf4j
@AllArgsConstructor
@Component
public class BatchService {
/** SqlSession */
private final SqlSessionTemplate sqlSessionTemplate;
/**
* 批量操作
* @param consumer 数据库操作
* @return boolean
* @author lcy
* @date 2022/4/8 16:03
**/
public boolean batchOperation(Consumer<SqlSession> consumer){
//获取批量sqlSession对象
SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH,false);
try {
//执行批量操作
consumer.accept(sqlSession);
sqlSession.commit();
} catch (Exception e) {
sqlSession.rollback();
log.error("批量操作失败",e);
return false;
} finally {
sqlSession.close();
}
return true;
}
}二、mybatisplus批量操作
上面的批量操作用于mybatisplus的时候,会出现如果失败了,失败之前的数据不会回滚。mybatisplus通过继承和实现他们的接口,自定义一些批量操作的接口。
**注意:**jdbc默认是不支持批量sql执行的,需要在sql连接上添加&allowMultiQueries=true
三、批量插入方法类
/**
* TODO
* @Author lcy
* @Date 2022/5/23 18:11
*/
@Slf4j
public class InsertBatchMethod extends AbstractMethod {
public InsertBatchMethod(String methodName){
super(methodName);
}
/**
* 批量插入数据
* @param mapperClass mapper的class
* @param modelClass 实体类的class
* @param tableInfo 表的信息
* @return org.apache.ibatis.mapping.MappedStatement
* @author lcy
* @date 2022/5/25 10:46
**/
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
final String sql = "<script>insert into %s %s values %s</script>";
final String fieldSql = prepareFieldSql(tableInfo);
final String valueSql = prepareValuesSql(tableInfo);
final String sqlResult = String.format(sql, tableInfo.getTableName(), fieldSql, valueSql);
log.debug("sqlResult----->{}", sqlResult);
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sqlResult, modelClass);
// 第三个参数必须和RootMapper的自定义方法名一致
return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatch", sqlSource, new NoKeyGenerator(), null, null);
}
private String prepareFieldSql(TableInfo tableInfo) {
StringBuilder fieldSql = new StringBuilder();
fieldSql.append(tableInfo.getKeyColumn()).append(",");
tableInfo.getFieldList().forEach(x -> {
fieldSql.append(x.getColumn()).append(",");
});
fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
fieldSql.insert(0, "(");
fieldSql.append(")");
return fieldSql.toString();
}
private String prepareValuesSql(TableInfo tableInfo) {
final StringBuilder valueSql = new StringBuilder();
valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
valueSql.delete(valueSql.length() - 1, valueSql.length());
valueSql.append("</foreach>");
return valueSql.toString();
}
}四、批量修改方法类
/**
* 批量更新方法实现,条件为主键,选择性更新
* @Author lcy
* @Date 2022/5/23 18:13
*/
@Slf4j
public class UpdateBatchMethod extends AbstractMethod {
public UpdateBatchMethod(String methodName){
super(methodName);
}
/**
* 通过mybatis的循环批量更新数据
* @param mapperClass mapper的class
* @param modelClass 实体类的class
* @param tableInfo 表的信息
* @return org.apache.ibatis.mapping.MappedStatement
* @author lcy
* @date 2022/5/25 10:44
**/
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass,Class<?> modelClass,TableInfo tableInfo){
String sql = "<script>\n<foreach collection=\"list\" item=\"item\" separator=\";\">\nupdate %s %s where %s=#{%s} %s\n</foreach>\n</script>";
String additional = tableInfo.isWithVersion() ? tableInfo.getVersionFieldInfo().getVersionOli("item","item.") : "" + tableInfo.getLogicDeleteSql(true,true);
String setSql = sqlSet(tableInfo.isWithLogicDelete(),false,tableInfo,false,"item","item.");
String sqlResult = String.format(sql,tableInfo.getTableName(),setSql,tableInfo.getKeyColumn(),"item." + tableInfo.getKeyProperty(),additional);
log.debug("sqlResult----->{}",sqlResult);
SqlSource sqlSource = languageDriver.createSqlSource(configuration,sqlResult,modelClass);
// 第三个参数必须和RootMapper的自定义方法名一致
return this.addUpdateMappedStatement(mapperClass,modelClass,"updateBatch",sqlSource);
}
}五、自定义方法注入器
/**
* 自定义方法SQL注入器
* @Author lcy
* @Date 2022/5/23 18:09
*/
public class CustomizedSqlInjector extends DefaultSqlInjector {
/**
* 如果只需增加方法,保留mybatis plus自带方法, 可以先获取super.getMethodList(),再添加add
* @param mapperClass mapper的class
* @param tableInfo 表对象
* @return java.util.List<com.baomidou.mybatisplus.core.injector.AbstractMethod>
* @author lcy
* @date 2022/5/23 18:20
**/
@Override public List<AbstractMethod> getMethodList(Class<?> mapperClass,TableInfo tableInfo){
List<AbstractMethod> methodList = super.getMethodList(mapperClass,tableInfo);
methodList.add(new InsertBatchMethod("insertBatch"));
methodList.add(new UpdateBatchMethod("updateBatch"));
return methodList;
}
}六、自定义批量mapper
/**
* 批量操作mapper
* @Author lcy
* @Date 2022/5/23 18:11
*/
public interface BatchBaseMapper<T> extends BaseMapper<T> {
/**
* 自定义批量插入 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
* @param list list集合
* @return int
* @author lcy
* @date 2022/5/23 18:13
**/
int insertBatch(@Param("list") List<T> list);
/**
* 自定义批量更新,条件为主键 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
* @param list list list集合
* @return int
* @author lcy
* @date 2022/5/23 18:13
**/
int updateBatch(@Param("list") List<T> list);
}七、修改配置文件
在mybatisplus配置文件增加
@Configuration
public class MybatisPlusConfiguration {
// 自定义sql注入器
@Bean
public CustomizedSqlInjector customizedSqlInjector(){
return new CustomizedSqlInjector();
}
}