前言
当操作大量数据的时候往往需要分批次去处理,以减少内存和i/o的压力,比如用?mybatis-plus,添加、修改、查询大量数据时候,会造成数据库压力太大,导致服务异常,还有在执行sql 的in 方法时候,参数不能大于1000个等问题,都需要进行批量处理。下面整理一个BatchUtil 批处理工具类,很好的解决以上的问题。
?工具类代码
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* 批处理工具类
*
* @version 1.0
* @since JDK1.8
* @author tarzan
* @date 2022年01月28日 16:39:50
*/
public class BatchUtil {
/**
* 批次数量
*/
public static final Integer NUMBER_BACH_PROTECT = 999;
/**
* 批量中包含有关联查询,可能因为数据过长出现数据查询的的问题,
* 这里进行分批处理
* @param list
* 需要处理的list
* @param bach
* 批量处理的函数
* @param <T>
* 元素类型
*/
public static <T> void protectBach(List<T> list, Consumer<List<T>> bach){
if (isEmpty(list)){return;}
if (list.size() > NUMBER_BACH_PROTECT) {
for (int i = 0; i < list.size(); i += NUMBER_BACH_PROTECT) {
int lastIndex = Math.min(i + NUMBER_BACH_PROTECT, list.size());
bach.accept(list.subList(i, lastIndex));
}
}else {
bach.accept(list);
}
}
/**
* 批量中包含有关联查询,可能因为数据过长出现数据查询的的问题
* 这里进行分批,合并数据处理。
* @param list
* 原数据
* @param bach
* 处理方法
* @param <T>
* 原数据类型
* @param <R>
* 处理结果类型
* @return
* 处理结果汇总
*/
public static <T, R> List<R> protectBach(List<T> list, Function<List<T>, List<R>> bach){
if (isEmpty(list)){return Collections.emptyList();}
if (list.size() > NUMBER_BACH_PROTECT) {
List<R> end = new LinkedList<>();
for (int i = 0; i < list.size(); i += NUMBER_BACH_PROTECT) {
int lastIndex = Math.min(i + NUMBER_BACH_PROTECT, list.size());
Optional.ofNullable(bach.apply(list.subList(i, lastIndex)))
.ifPresent(end::addAll);
}
return end;
}
return bach.apply(list);
}
private static <T> boolean isEmpty(Collection<T> collection) {
return collection == null || collection.isEmpty();
}
}
使用教程
比如 数据操作A和B表,A表是主表,B是子表,当批量删除A表的数据,同时删除B表关联的数据,代码如下
/**
* 方法描述: 删除
*
* @param ids
* @return {@link boolean}
*/
@Transactional(rollbackFor = Throwable.class)
public boolean delete(List<Long> ids) {
if(CollectionUtils.isEmpty(ids)){
return true;
}
removeByIds(ids);
return attributeSetService.deleteByClazz(ids);
}
/**
* 方法描述: 根据要素集删除
*
* @param setIds
* @return {@link boolean}
*/
@Transactional(rollbackFor = Throwable.class)
protected boolean delBySets(List<Long> setIds) {
LambdaQueryWrapper<FeatureClazzEntity> wrapper=new LambdaQueryWrapper();
wrapper.select(FeatureClazzEntity::getId).in(FeatureClazzEntity::getFeatureSetId,setIds);
List<Long> ids=list(wrapper).stream().map(FeatureClazzEntity::getId).collect(Collectors.toList());
BatchUtil.protectBach(ids, this::delete);
return true;
}
?批量查询
比如 数据操作A和B表,A表是主表,B是子表,根据A表的数据,查出B表关联的数据,代码如下
protected List<AttributeSetEntity> selectBySets(List<Long> setIds) {
LambdaQueryWrapper<FeatureClazzEntity> wrapper=new LambdaQueryWrapper();
wrapper.select(FeatureClazzEntity::getId).in(FeatureClazzEntity::getFeatureSetId,setIds);
List<Long> ids=list(wrapper).stream().map(FeatureClazzEntity::getId).collect(Collectors.toList());
List<AttributeSetEntity> result= BatchUtil.protectBach(ids, idList->{
return attributeSetService.lambdaQuery().in(AttributeSetEntity::getClazzId,idList).list();
});
return result;
}
|