【Java】批量操作優化

批量獲取

開發中,有時候難免需要用到類似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()));
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章