需求描述:在进行数据同步时需要把SQLserver的数据表同步到MySQL的数据库表,有的表字段一样,但有的却字段类型不一样,需要进转换单独的转换,所以写了一个工具类实现,少写代码。
1、定义一个函数式接口
函数式接口里包含默认方法,这里我们定义默认回调方法。
- /**
- * 集合数据拷贝工具类扩展回调函数
- *
- * @author QC
- * @version V1.0
- * @since 2022-08-14
- */
- @FunctionalInterface
- public interface BeanUtilCopyCallBack
{ - /**
- * 定义默认回调方法
- *
- * @param target 目标对象
- * @param source 源对象
- */
- void callBack(S source, T target);
- }
-
2、封装一个工具类BeanUtilCopy.java
-
-
- import java.util.ArrayList;
- import java.util.List;
- import java.util.function.Supplier;
-
- import org.springframework.beans.BeanUtils;
-
- /**
- * 集合数据拷贝工具类封装
- *
- * @author QC
- * @version V1.0
- * @since 2022-08-14
- */
- public class BeanUtilCopy extends BeanUtils {
-
- /**
- * 集合数据的拷贝
- *
- * @param sources: 数据源类
- * @param target: 目标类::new(eg: UserVO::new)
- * @return list 目标数据对象列表
- */
- public static
List copyListProperties(List sources, Supplier target) { - return copyListProperties(sources, target, null);
- }
-
- /**
- * 带回调函数的集合数据的拷贝(可自定义字段拷贝规则)
- *
- * @param sources: 数据源类
- * @param target: 目标类::new(eg: UserVO::new)
- * @param copyCallBack: 回调函数 用于扩展修改字段数据类型,比如int改为string
- * @return list 目标数据对象列表
- */
- public static
List copyListProperties(List sources, Supplier target, BeanUtilCopyCallBack copyCallBack) { - List
list = new ArrayList<>(sources.size()); - for (S source : sources) {
- T targetData = target.get();
- copyProperties(source, targetData);
- list.add(targetData);
- if (copyCallBack != null) {
- copyCallBack.callBack(source, targetData); // 回调
- }
- }
- return list;
- }
- }
-
-
通过如上方法,基本实现了集合的拷贝,但是从返回结果我们可以发现:属性不同的字段无法拷贝。比如:UserDO.java 和UserVO.java 最后一个字段sn类型不一样,分别是:Integer/String
使用案例如下:
通过这个扩展就基本可解决各种类型转换了,该方法是我用的最多的方案,这里简单封装下,可以方便集合类型对象的拷贝,平常使用基本够用,仅供参考。
- /**
- * 同步到 Mysql-master(yth-yjt) 库
- *
- * @param originalData SQL Server-gwyj 库原始数据
- */
- private void executeMasterSync(List
originalData) { - //查询目标库是否存在数据
- List
originalDataIDs = originalData.stream().filter(Objects::nonNull) - .map(entity -> String.valueOf(entity.getSn())).collect(Collectors.toList());
- List
originalDatas = targetStMntrltmService.lambdaQuery() - .in(StMntrltmEntity::getSn, originalDataIDs)
- .orderByDesc(StMntrltmEntity::getSn).list();
- Set
ids = originalDatas.stream().filter(Objects::nonNull).map(StMntrltmEntity::getSn).collect(Collectors.toSet()); - //转换为目标库实体
- List
targetData = BeanUtilCopy.copyListProperties(originalData, StMntrltmEntity::new, (originalObj, targetObj) -> { - targetObj.setSn(String.valueOf(originalObj.getSn()));//转换源数据的主键ID为String类型和目标表保持一致
- targetObj.setTm(DateUtils.dateCovertLocalDateTime(originalObj.getTm()));//date转localDateTime
- if (Objects.nonNull(originalObj.getOvvlu()))
- targetObj.setOvvlu(BigDecimal.valueOf(originalObj.getOvvlu()));//double 转 BigDecimal
- if (Objects.nonNull(originalObj.getVlu()))
- targetObj.setVlu(BigDecimal.valueOf(originalObj.getVlu()));//double 转 BigDecimal
- if (Objects.nonNull(originalObj.getVlu1()))
- targetObj.setVlu1(BigDecimal.valueOf(originalObj.getVlu1()));//double 转 BigDecimal
- });
- Map
> partitioningMap = targetData.stream() - .collect(Collectors.partitioningBy(entity -> ids.contains(entity.getSn())));//数据分割,包含的分为updateData,未包含的分为insertData
- List
insertData = partitioningMap.get(false); - List
updateData = partitioningMap.get(true); - if (!CollectionUtils.isEmpty(updateData)) {
- targetStMntrltmService.saveOrUpdateBatch(updateData);
- }
- if (!CollectionUtils.isEmpty(insertData)) {
- targetStMntrltmService.saveBatch(insertData);
- }
- }
其中用到了很多Java8新的写法,比如使用流来处理数据列表,::拉姆达表达式的简写,拉姆达表达式,集合的分组等等。
扩展知识:对象的拷贝
Java中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。
对象拷贝分为浅拷贝(浅克隆)与深拷贝(深克隆)。
浅拷贝与深拷贝差异
参考文献: