批量获取
开发中,有时候难免需要用到类似findAll()方法,或者说获取表中所有数据。但是当这个量很大时,一次性从数据库中加载到内存中,明显不理智。这时候可以采用批量取的方式,比如batchSize为500。
/**
* 批量获取任务,删除任务
*/
private void cleanTask() {
List<String> projectIds = getAllProjectIds();
if (isNotEmpty(projectIds)) {
int skip = 0;
List<TaskVO> res = null;
do {
res = taskService.findAll(skip, batchSize);
if (res == null || res.isEmpty()) {
break;
}
deleteBatchTask(projectIds, res);
skip = skip + batchSize;
} while (res.size() == batchSize);
}
}
批量删除
在执行删除操作时,通常我们会foreach遍历着删,但是遍历一次就是与数据库的一次交互。更常见地,每一次删除时,还会有很多相关的级联删除操作,这样更加拉低了页面的相应。有几个地方可以优化:比如采用线程池来执行整个的批量删除操作;比如可以先做假删除,在夜深人静时采用定时任务来删除;再比如,采用批量删除,也就是in语句。这里主要说的也是第三种,但是如果采用in进行批量删除,也需要注意,不能过分信任in的批量,如果数据量过大,一次性in上万条,数据库也扛不住,此时就可以对in再进行批量。
// 批量删除任务
Functional.batchExec(taskIds, delIds -> taskDAO.deleteTaskTrue(delIds), batchSize);
/**
* 批量删除(真删除)
*
* @param taskIds 任务ids
*/
public void deleteTaskTrue(List<String> taskIds) {
createDelete().where().in("_id", taskIds).delete();
}
public class Functional {
/**
* 将集合按指定分批大小进行分批操作
*
* @param src
* @param function
* @param batchSize
* @param <K>
*/
public static <K> void batchExec(List<K> src, Consumer<List<K>> function, int batchSize) {
if (src == null || src.isEmpty()) {
return;
}
if (batchSize <= 0) {
batchSize = 1;
}
int loopTimes;
if (src.size() % batchSize == 0) {
loopTimes = src.size() / batchSize;
} else {
loopTimes = src.size() / batchSize + 1;
}
for (int i = 0; i < loopTimes; i++) {
List<K> subList;
if (i == src.size() / batchSize) {
subList = src.subList(i * batchSize, src.size());
} else {
subList = src.subList(i * batchSize, (i + 1) * batchSize);
}
function.accept(subList);
}
}
/**
* 正序排序
*
* @param src
* @param field
*/
public static void ascSort(List src, String field) {
sort(src, field, 1);
}
/**
* 逆序排序
*
* @param src
* @param field
*/
public static void descSort(List src, String field) {
sort(src, field, -1);
}
private static void sort(List src, String field, int direction) {
if (ValidateUtil.isEmpty(src)) {
return;
}
Collections.sort(src, new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
Object value1 = BeanUtil.pojo.getProperty(o1, field);
Object value2 = BeanUtil.pojo.getProperty(o2, field);
if (value1 != null && value2 != null) {
if (value1 instanceof Long) {
return ((Long) value1).compareTo((Long) value2) * direction;
}
if (value1 instanceof Integer) {
return ((Integer) value1).compareTo((Integer) value2) * direction;
}
if (value1 instanceof Double) {
return ((Double) value1).compareTo((Double) value2) * direction;
}
if (value1 instanceof BigDecimal) {
return ((BigDecimal) value1).compareTo((BigDecimal) value2) * direction;
}
if (value1 instanceof Date) {
return ((Date) value1).compareTo((Date) value2) * direction;
}
if (value1 instanceof String) {
return ((String) value1).compareTo((String) value2) * direction;
}
}
return 0;
}
});
}
/**
* 除重
*
* @param src
* @param <K>
* @return
*/
public static <K> List<K> distinct(List<K> src) {
if (ValidateUtil.isEmpty(src)) {
return src;
}
return new ArrayList<K>(src.stream().collect(Collectors.toSet()));
}
}