如何利用Javers的Diff结果创建仅含变更字段的实体对象?
用Javers生成仅含变更字段的实体对象
刚接触Javers的话,确实会想有没有现成的快捷方式来生成这种只保留变更字段的实体——可惜Javers本身并没有直接提供这个功能,但我们可以利用它返回的Diff对象里的变更信息,结合反射或者Bean工具类来轻松实现,步骤其实很简单:
步骤1:调整实体类适配null值
首先你的Person类如果要支持字段为null,建议把基本类型换成包装类(比如int改成Integer),同时加上无参构造器方便创建空实例:
@AllArgsConstructor @NoArgsConstructor class Person { @Id String name; Integer age; String address; }
步骤2:获取Diff对象并提取变更记录
先通过Javers.compare()拿到两个对象的差异,然后从Diff里筛选出所有属性变更:
Person person1 = new Person("Bob", 20, "Brooklyn"); Person person2 = new Person("Bob", 25, "Queens"); Javers javers = JaversBuilder.javers().build(); Diff diff = javers.compare(person1, person2); // 获取所有属性变更的记录 List<PropertyChange> propertyChanges = diff.getChangesByType(PropertyChange.class);
步骤3:构建仅含变更字段的实体
创建一个空的Person实例,然后遍历变更记录,只把发生变更的字段设置为新值(来自person2),其他字段保持null:
// 创建空实例,所有字段初始为null Person changedOnlyPerson = new Person(); // 遍历变更,给对应字段赋值 for (PropertyChange change : propertyChanges) { String fieldName = change.getPropertyName(); Object newValue = change.getRightValue(); // 变更后的新值 // 用Spring的BeanUtils简化属性设置(没有Spring的话也可以自己写反射逻辑) try { org.springframework.beans.BeanUtils.setProperty(changedOnlyPerson, fieldName, newValue); } catch (Exception e) { e.printStackTrace(); } }
这样生成的changedOnlyPerson就只有age(25)和address(Queens)有值,name保持null——完全符合你“仅保留变更字段,其余为null”的需求。
小补充
- 如果实体的ID字段也可能发生变更(虽然业务上一般不建议),这个逻辑也能自动处理,因为ID字段的变更也会被Javers捕获到。
- 要是不想依赖Spring的工具类,用JDK原生反射也能实现字段赋值,只是代码会稍微繁琐一点,核心逻辑都是遍历变更记录然后设置对应字段。
内容的提问来源于stack exchange,提问作者knk
相关产品推荐
相关产品推荐

