MybatisPlus扩展实现批量新增与更新
MybatisPlus批量操作
- 使用过
Mybatis_Plus
的都知道,Mybatis_Plus
的批量操作只有在IService
才有(saveBatch
|saveOrUpdateBatch
),且通过源码可以看到,是通过批次以及单条进行操作的
/**
* 执行批量操作
*
* @param entityClass 实体类
* @param log 日志对象
* @param list 数据集合
* @param batchSize 批次大小
* @param consumer consumer
* @param <E> T
* @return 操作结果
* @since 3.4.0
*/
public static <E> boolean executeBatch(Class<?> entityClass, Log log, Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
Assert.isFalse(batchSize < 1, "batchSize must not be less than one");
return !CollectionUtils.isEmpty(list) && executeBatch(entityClass, log, sqlSession -> {
int size = list.size();
int idxLimit = Math.min(batchSize, size);
int i = 1;
for (E element : list) {
consumer.accept(sqlSession, element);
if (i == idxLimit) {
sqlSession.flushStatements();
idxLimit = Math.min(idxLimit + batchSize, size);
}
i++;
}
});
}
Mybatis_Plus
的BaseMapper
并没有提供批量方法,所以我们可以自己来扩展一下BaseMapper
,使它也拥有批量方法,方便我们在Service
层进行业务处理后也能使用批量操作。
MybatisPlus批量扩展实现
自定义批量新增方法
/**
* @version 1.0.0
* @className: InsertBatchMethod
* @description: MP批量新增
* @author: LiJunYi
* @create: 2023/2/28 16:22
*/
@Slf4j
public class InsertBatchMethod extends AbstractMethod {
private static final long serialVersionUID = 2074909358033325037L;
/**
* 构造函数
*
* @param methodName 方法名称
*/
protected InsertBatchMethod(String methodName) {
super(methodName);
}
/**
* 注入自定义 MappedStatement
*
* @param mapperClass mapper类
* @param modelClass 模型类
* @param tableInfo 表信息
* @return {@link MappedStatement}
*/
@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);
// 第三个参数必须和SuperMapper的自定义方法名一致
return this.addInsertMappedStatement(mapperClass, modelClass, "insertBatch", sqlSource, new NoKeyGenerator(), null, null);
}
/**
* 表字段信息SQL
*
* @param tableInfo 表信息
* @return {@link String}
*/
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();
}
/**
* 要新增的数据SQL
*
* @param tableInfo 表信息
* @return {@link String}
*/
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();
}
}
自定义批量更新方法
/**
* @version 1.0.0
* @className: UpdateBatchMethod
* @description: 批量更新
* @author: LiJunYi
* @create: 2023/2/28 16:23
*/
@Slf4j
public class UpdateBatchMethod extends AbstractMethod {
private static final long serialVersionUID = 8584770698297436989L;
protected UpdateBatchMethod(String methodName) {
super(methodName);
}
/**
* 注入自定义 MappedStatement
*
* @param mapperClass mapper类
* @param modelClass 模型类
* @param tableInfo 表信息
* @return {@link MappedStatement}
*/
@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);
// 第三个参数必须和SuperMapper的自定义方法名一致
return this.addUpdateMappedStatement(mapperClass, modelClass, "updateBatch", sqlSource);
}
}
SQL注入器注入
/**
* @version 1.0.0
* @className: CustomizedSqlInjector
* @description: SQL注入器
* @author: LiJunYi
* @create: 2023/2/28 16:25
*/
public class CustomizedSqlInjector extends DefaultSqlInjector {
/**
* 如果只需增加方法,保留mybatis plus自带方法,
* 可以先获取super.getMethodList(),再添加add
*/
@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(mapperClass,tableInfo);
methodList.add(new InsertBatchMethod("批量新增方法"));
methodList.add(new UpdateBatchMethod("批量更新方法"));
return methodList;
}
}
MP配置
@Configuration
@MapperScan("com.xx.module.yy.**.dao")
public class MybatisPlusConfig
{
@Bean
public CustomizedSqlInjector customizedSqlInjector() {
return new CustomizedSqlInjector();
}
}
自定义SuperMapper
- 注意这个类不要让
mp
扫描到!!
package com.xx.module.framework.mybatis;
/**
* @version 1.0.0
* @className: SuperMapper
* @description: 注意这个类不要让 mp 扫描到!!
* @author: LiJunYi
* @create: 2023/2/28 16:27
*/
public interface SuperMapper<T> extends BaseMapper<T> {
/**
* 自定义批量插入
*
* @param entityList 实体对象集合
* @return int
*/
int insertBatch(@Param("list") Collection<T> entityList);
/**
* 自定义批量更新
*
* @param entityList 实体对象集合
* @return int
*/
int updateBatch(@Param("list") Collection<T> entityList);
}
IBasicService
/**
* @version 1.0.0
* @className: IBasicService
* @description:
* @author: LiJunYi
* @create: 2023/2/28 16:34
*/
public interface IBasicService<T> extends IService<T> {
/**
* 批量插入
* @param entityList 实体对象集合
* @return int
*/
int insertBatch(Collection<T> entityList);
/**
* 批处理更新
* @param entityList 实体对象集合
* @return int
*/
int updateBatch(Collection<T> entityList);
}
IBasicService实现类
/**
* @version 1.0.0
* @className: BasicServiceImpl( 泛型:M 是 mapper 对象,T 是实体 )
* @description:
* @author: LiJunYi
* @create: 2023/2/28 16:34
*/
public class BasicServiceImpl<M extends SuperMapper<T>, T> extends ServiceImpl<M, T> implements IBasicService<T> {
/**
* 批量新增
*
* @param entityList 实体对象集合
* @return int
*/
@Override
public int insertBatch(Collection<T> entityList) {
return baseMapper.insertBatch(entityList);
}
/**
* 批量更新
*
* @param entityList 实体对象集合
* @return int
*/
@Override
public int updateBatch(Collection<T> entityList) {
return baseMapper.updateBatch(entityList);
}
}
如何使用
只需要将原先继承BaseMapper
的修改为SuperMapper
即可
public interface xxDao extends BaseMapper<xxModel> {}
public interface xxDao extends SuperMapper<xxModel> {}