Javers

在开发过程中遇到需求,比较数据库中的原数据与新修改要写入库中的数据。这个实体类是比较复杂的。例如有基本类型,BigDecimal类型,自定义类型,Date类型,List集合,Set集合,Map集合等。在比较复杂的类的情况下,使用Objects的equals是不适用的。所以为了解决这个问题,可以使用Javers库中的compare方法来解决该问题

引入

 <!-- https://mvnrepository.com/artifact/org.javers/javers-core -->
<dependency>
<groupId>org.javers</groupId>
<artifactId>javers-core</artifactId>
<version>6.6.2</version>
</dependency>

方法:

Javers javers = JaversBuilder.javers().build();
Diff diff = javers.compare(oldObject,newObject)
boolean flag = diff.hasChange();
//diff会在控制台打印出两个类之间的异同,相同不打印数据,不同会展示出修改前后的数据
//diff.hasChange(); 如果两个类完全相同,返回值为flase,两个类不同,返回值为true

示例

public static void main(String[] args) {
Javers build = JaversBuilder.javers().build();
//A系统的类
//数据库中的数据
PromotionDetail promotionDetail = new PromotionDetail();
promotionDetail.setCanEditFlag(true);
promotionDetail.setAllGoodsCountType(1);
promotionDetail.setName("name1");
PromotionGoods promotionGoods = new PromotionGoods();
promotionGoods.setCount(1);
promotionGoods.setDeptName("deptname1");
PromotionGoods promotionGoods1 = new PromotionGoods();
promotionGoods1.setCount(2);
promotionGoods1.setDeptName("deptname2");
List<PromotionGoods> list = new ArrayList<>();
list.add(promotionGoods);
list.add(promotionGoods1);
promotionDetail.setGoods(list); //新数据
PromotionDetail promotionDetail1 = new PromotionDetail();
promotionDetail1.setCanEditFlag(true);
promotionDetail1.setAllGoodsCountType(1);
promotionDetail1.setName("name2");
PromotionGoods promotionGoods2 = new PromotionGoods();
promotionGoods2.setCount(5);
promotionGoods2.setDeptName("deptname3");
PromotionGoods promotionGoods3 = new PromotionGoods();
promotionGoods3.setCount(4);
promotionGoods3.setDeptName("deptname3");
List<PromotionGoods> list0 = new ArrayList<>();
list0.add(promotionGoods2);
list0.add(promotionGoods3);
promotionDetail1.setGoods(list0); Diff compare = build.compare(promotionDetail, promotionDetail1);
boolean b = compare.hasChanges();
System.out.println(compare);
System.out.println(b);
}
//控制台输出
Diff:
* changes on com.ef.admin.data.controller.promotion.np.param.PromotionDetail/ :
- 'goods/0.count' changed: '1' -> '5'
- 'goods/0.deptName' changed: 'deptname1' -> 'deptname3'
- 'goods/1.count' changed: '2' -> '4'
- 'goods/1.deptName' changed: 'deptname2' -> 'deptname3'
- 'name' changed: 'name1' -> 'name2' true ====》为true说明有改变

遇到的问题:

  • BigDecimal

    在比较BigDecimal类型的不同数据时,会出现问题。由于javer.compare()底层是使用的objects的equals方法来判断两个数据是否相等,而BigDecimal类型比较时使用equals方法比较存在问题,应该使用BigDecimal类中的compareTo方法比较,详见https://blog.csdn.net/molihuaya/article/details/79139418

    BigDecimalComparatorWithFixedEquals类实现了CustomValueComparator<>接口并重写equals方法

    public class BigDecimalComparatorWithFixedEquals implements CustomValueComparator<BigDecimal> {
    @Override
    public boolean equals(BigDecimal a, BigDecimal b) {
    return a.compareTo(b) == 0;
    }

    所以创建javers对象时:

    Javers javers = JaversBuilder.javers().registerValue(BigDecimal.class,new BigDecimalComparatorWithFixedEquals()).build();
  • Date

    在比较Date类型的不同数据时,会出现问题。假设在数据中查出的日期类型为Date,新修改的数据为TimeStamp类型。此时使用javers.compare()比较时即使时间点相同,比较出来仍有问题。

    数据库中的数据  2022-02-25 23:59:59.0
    新修改的数据 Fri Feb 25 23:59:59 CST 2022

    可以通过实现CustomValueComparator<>接口来重写equals方法

    public class EfDateComparator implements CustomValueComparator<Date> {
    @Override
    public boolean equals(Date a, Date b) {
    return a.getTime() == b.getTime();
    }

    所以创建javers对象时:

    Javers javers = JaversBuilder.javers().registerValue(BigDecimal.class,new BigDecimalComparatorWithFixedEquals()).build();
Javers javers = JaversBuilder.javers()
.registerValue(BigDecimal.class,new BigDecimalComparatorWithFixedEquals())
.registerValue(BigDecimal.class,new BigDecimalComparatorWithFixedEquals())
.build();

相关注解

在比较两个类时,可能需要只比较部分字段或不比较部分字段,可以考虑使用以下两个注解

//在一个类中,在字段上添加该注解,该类中只比较有注解的字段
@DiffInclude //在一个类中,在字段上添加该注解,该类中忽略比较有注解的字段
@DiffIgnore //PS:两个注解不可以同时出现在一个类中

如果有没说明白的地方可以留言

Javers 比较两个类的差异的更多相关文章

  1. 通过实现System.IComparable接口的CompareTo方法对两个类进行比较

    假设现在有一个学生类 class Student { int age; public Student(int age) { this.age = age; } } 要使学生类之间能进行比较,实现Sys ...

  2. 【java回调】java两个类之间的回调函数传递

    背景交代:熟悉用js开发的cordovaAPP:对java一窍不通的我,老师让做一个监测用户拍照事件的功能,无奈没有找到现成的库,无奈自己动手开发java插件~~0基础java GreenHand,祝 ...

  3. ORACLE如何比较两个数据库的差异

    ORACLE怎么比较两个数据库的差异 方法1:使用PL-SQL工具 点击 工具->比较用户对象

  4. diff 比较两个文件的差异

    功能:比较两个文件的差异,并把不同地方的信息显示出来.默认diff格式的信息. diff比较两个文件或文件集合的差异,并记录下来,生成一个diff文件,这也是我们常说的补丁文件.也使用patch命令对 ...

  5. Reader与InputStream两个类中的read()的区别

    InputStream类的read()方法是从流里面取出一个字节,他的函数原型是 int read(); ,Reader类的read()方法则是从流里面取出一个字符(一个char),他的函数原型也是  ...

  6. 简单看看这两个类 String和StringBuilder

    我记得以前在园子里面讨论这两个类的文章有很多很多,并且还拿出了很多的测试报告,在什么情况下,谁比谁快,在什么情况下,该用谁 不该用谁等等这些,我这里就不比较了,我就简单看看他们里面的内部实现,那就先看 ...

  7. git日志输出格式及两个版本之间差异列表

    查看commit id git log --pretty=format:"%h" git log --pretty=format:"%H" 获取两个版本间差异的 ...

  8. C++学习笔记一 —— 两个类文件互相引用的处理情况

    先记录一些零碎的知识点: 1. 一个类可以被声明多次,但只能定义一次,也就是可以 class B;  class B;  class B; ……;  class B {……};  这样子. 2. 一个 ...

  9. 使用 Attribute +反射 来对两个类之间动态赋值

    看同事使用的 一个ORM 框架 中 有这样一个功能  通过特性(附加属性)的功能来 实现的两个类对象之间动态赋值的 功能 觉得这个功能不错,但是同事使用的 ORM 并不是我使用的  Dapper  所 ...

随机推荐

  1. 带你自定义实现Spring事件驱动模型

    Spring 事件驱动模型概念 Spring 事件驱动模型就是观察者模式很经典的一个应用,我们可以通过Spring 事件驱动模型来完成代码的解耦. 三角色 Spring 事件驱动模型或者说观察者模式需 ...

  2. RocketMQ 介绍与安装

    目录 RocketMQ 介绍 MQ 介绍 MQ 作用 MQ 缺点 MQ 常见产品 RocketMQ 简介 RocketMQ 架构 RocketMQ 安装 RocketMQ 介绍 MQ 介绍 定义: M ...

  3. Java包装类和处理对象

    Java中基本类型变量和字符串之间的转换 public class Primitive2String { public static void main(String args[]) { String ...

  4. fluem读取文件并写入到hadoop的hdfs

    接上一章,本章介绍使用 crontab 像指定文件定时写入,使用fluem 读取并写入到hadoop的hdfs 前提准备已安装好fluem ,和hadoop(推荐单机即可毕竟做实验) 一.进入终端执行 ...

  5. 【刷题-LeetCode】190 Reverse Bits

    Reverse Bits Reverse bits of a given 32 bits unsigned integer. Example 1: Input: 0000001010010100000 ...

  6. 配置vscode的C++环境Unexpected GDB output from command "-environment-cd

    原因 中文字符 换成D盘目录下以后.

  7. 动态代理jdk的Proxy与spring的CGlib

    1. 为什么要使用动态代理? 动态代理:在不改变原有代码的情况下上进行对象功能增强 使用代理对象代替原来的对象完成功能 进而达到拓展功能的目的 2.JDK Proxy 动态代理面向接口的动态代理 特点 ...

  8. 机器学习-softmax回归 python实现

    ---恢复内容开始--- Softmax Regression 可以看做是 LR 算法在多分类上的推广,即类标签 y 的取值大于或者等于 2. 假设数据样本集为:$\left \{ \left ( X ...

  9. 【程序18】求s=a+aa+aaa+aaaa+aa...a的值

    求s=a+aa+aaa+aaaa+aa-a的值,其中a是一个数字.例如2+22+222+2222+22222(此时共有5个数相加),几个数相加由键盘控制. 知识点:在Python 3里,reduce( ...

  10. Java 基础02

    参照:https://www.cnblogs.com/ZXF6/p/11530009.html 类和对象 /** * java 中的类和对象 * * 一.局部变量的作用域. * * 二.面向对象的概述 ...