【后端工具】往表里合并数据工具方法,通过BatchSql实现MergeData

背景

A系统的数据往B系统同步,订单主表、订单子表,一对多的关系。当订单发生修改,在同步子表数据的时候,如果子表数据多了或者少了的情况,逻辑是

        1、表里多的数据,删掉(本文示例做的是物理删除,可根据需求进行修改)

        2、表里少的数据,插入

        3、相同的数据,更新

为了方便使用,写了个共通的方法,需要的供参考

代码

两个方法支持相同实体、不相同实体

    /**
     * 相同表merge
     *
     * @param list           从表里查出来的数据
     * @param getKeyFunction 获取T的唯一标识
     * @param mapperClass    T的mapper
     * @param wrapper        T的更新条件
     * @param <T>
     */
    @DSTransactional
    public <T> void mergeData(List<T> list, List<T> sourceList, Function<T, Object> getKeyFunction, Class mapperClass, Function<T, Wrapper> wrapper) {

        // 找多的数据,删除(list有,sourceList没有)
        List<T> deleteList = list.stream()
                .filter(item -> sourceList.stream().noneMatch(syncItem -> getKeyFunction.apply(syncItem).equals(getKeyFunction.apply(item))))
                .collect(Collectors.toList());
        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(deleteList)) {
            DynamicBatchSqlUtil.batchDelete(deleteList, mapperClass, wrapper);
        }

        // 找相同的数据,更新(list有,sourceList有)
        List<T> updateList = list.stream()
                .filter(item -> sourceList.stream().anyMatch(syncItem -> getKeyFunction.apply(syncItem).equals(getKeyFunction.apply(item))))
                .collect(Collectors.toList());

        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(updateList)) {
            DynamicBatchSqlUtil.batchUpdate(updateList, mapperClass, wrapper);
        }

        // 找Sync新增的数据(list没有,sourceList有)
        List<T> insertList = sourceList.stream()
                .filter(item -> list.stream().noneMatch(syncItem -> getKeyFunction.apply(syncItem).equals(getKeyFunction.apply(item))))
                .collect(Collectors.toList());

        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(insertList)) {
            DynamicBatchSqlUtil.batchInsert(insertList, mapperClass);
        }

        list.addAll(insertList);
    }

    /**
     * 两个不同的表merge
     *
     * @param list           从表里查出来的数据
     * @param syncList       需要merge到表里的数据
     * @param syncFunction   R转T
     * @param getKeyFunction 获取T的唯一标识
     * @param mapperClass    T的mapper
     * @param wrapper        T的更新条件
     * @param <T>
     * @param <R>
     */
    public <T, R> void mergeData(List<T> list, List<R> syncList, Function<R, T> syncFunction, Function<T, Object> getKeyFunction, Class mapperClass, Function<T, Wrapper> wrapper) {

        // 先把数据转成一样的
        List<T> sourceList = syncList.stream().map(syncFunction).collect(Collectors.toList());

        mergeData(list, sourceList, getKeyFunction, mapperClass, wrapper);
    }
DynamicBatchSqlUtil
@Component
public class DynamicBatchSqlUtil {

    private static String defaultDsKey;

    public static final String SQL_TYPE_INSERT = "INSERT";

    public static final String SQL_TYPE_UPDATE = "UPDATE";

    public static final String SQL_TYPE_DELETE = "DELETE";

    /**
     * 给静态变量赋值
     *
     * @param defaultDsKey
     */
    @Value("${spring.datasource.dynamic.primary}")
    public void setDefaultDsKey(String defaultDsKey) {
        this.defaultDsKey = defaultDsKey;
    }

    /**
     * 批量插入
     *
     * @param list        数据
     * @param mapperClass 执行数据的mapper的CLass
     * @return
     */
    public static <T> int batchInsert(List<T> list, Class mapperClass) {
        DS ds = (DS) mapperClass.getAnnotation(DS.class);
        // Mapper没有注解,就使用默认的
        String dsKey = ds != null ? ds.value() : defaultDsKey;
        return batchInsert(SQL_TYPE_INSERT, dsKey, list, mapperClass, null);
    }

    /**
     * 批量更新
     *
     * @param list        数据
     * @param mapperClass 执行数据的mapper的CLass
     * @return
     */
    public static <T> int batchUpdate(List<T> list, Class mapperClass, Function<T, Wrapper> wrapper) {
        DS ds = (DS) mapperClass.getAnnotation(DS.class);
        // Mapper没有注解,就使用默认的
        String dsKey = ds != null ? ds.value() : defaultDsKey;
        return batchInsert(SQL_TYPE_UPDATE, dsKey, list, mapperClass, wrapper);
    }

    /**
     * 批量删除
     *
     * @param list        数据
     * @param mapperClass 执行数据的mapper的CLass
     * @return
     */
    public static <T> int batchDelete(List<T> list, Class mapperClass, Function<T, Wrapper> wrapper) {
        DS ds = (DS) mapperClass.getAnnotation(DS.class);
        // Mapper没有注解,就使用默认的
        String dsKey = ds != null ? ds.value() : defaultDsKey;
        return batchInsert(SQL_TYPE_DELETE, dsKey, list, mapperClass, wrapper);
    }

    /**
     * 批量插入
     *
     * @param type        sql类型
     * @param dsKey       数据源
     * @param list        数据
     * @param mapperClass 执行数据的mapper的CLass
     * @return
     */
    public static <T> int batchInsert(String type, String dsKey, List<T> list, Class mapperClass, Function<T, Wrapper> wrapper) {
        DynamicDataSourceContextHolder.push(dsKey);
        try {
            return SQL_TYPE_INSERT.equals(type) ? batchInsertExecute(list, mapperClass)
                    : SQL_TYPE_UPDATE.equals(type) ? batchUpdateExecute(list, mapperClass, wrapper)
                    : SQL_TYPE_DELETE.equals(type) ? batchDeleteExecute(list, mapperClass, wrapper) : 0;
        } finally {
            DynamicDataSourceContextHolder.poll();
        }
    }

    /**
     * 批量插入
     *
     * @param list
     * @param mapperClass
     * @return
     */
    public static <T> int batchInsertExecute(List<T> list, Class mapperClass) {
        SqlSessionFactory sqlSessionFactory = SpringUtils.getBean("sqlSessionFactory");
        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {

            Object mapper = sqlSession.getMapper(mapperClass);

            list.forEach(((MyBaseMapper) mapper)::insert);

            sqlSession.flushStatements();
            sqlSession.commit();
        }
        return list.size();
    }

    /**
     * 批量更新
     *
     * @param list
     * @param mapperClass
     * @param wrapper     更新条件
     * @return
     */
    public static <T> int batchUpdateExecute(List<T> list, Class mapperClass, Function<T, Wrapper> wrapper) {
        SqlSessionFactory sqlSessionFactory = SpringUtils.getBean("sqlSessionFactory");
        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {

            Object mapper = sqlSession.getMapper(mapperClass);

            list.forEach(obj -> {
                ((MyBaseMapper) mapper).update(obj, wrapper.apply(obj));
            });

            sqlSession.flushStatements();
            sqlSession.commit();
        }
        return list.size();
    }

    /**
     * 批量删除
     *
     * @param list
     * @param mapperClass
     * @param wrapper     删除条件
     * @return
     */
    public static <T> int batchDeleteExecute(List<T> list, Class mapperClass, Function<T, Wrapper> wrapper) {
        SqlSessionFactory sqlSessionFactory = SpringUtils.getBean("sqlSessionFactory");
        try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {

            Object mapper = sqlSession.getMapper(mapperClass);

            list.forEach(obj -> {
                ((MyBaseMapper) mapper).delete(wrapper.apply(obj));
            });

            sqlSession.flushStatements();
            sqlSession.commit();
        }
        return list.size();
    }
}

参考:

Jdk8函数接口Supplier、Function、Predicate、Consumer、BiFunction、BiPredicate、BiConsumer

Mybatisplus多数据源batchInsert

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值