首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何让Javers根据字段值而不是ID/对象引用进行比较

Javers是一个开源的Java库,用于比较Java对象的差异。默认情况下,Javers根据对象的ID或对象引用来进行比较。然而,有时候我们希望根据字段值来进行比较,而不是依赖于对象的标识。

要让Javers根据字段值而不是ID/对象引用进行比较,可以使用Javers的自定义比较器功能。自定义比较器允许您根据自己的需求定义对象比较的方式。

下面是一些步骤来实现这个目标:

  1. 创建一个实现了Comparator接口的自定义比较器类。该接口定义了compare方法,用于比较两个对象的差异。在这个方法中,您可以根据字段值来进行比较。
  2. 在自定义比较器类中,使用Javers提供的PropertyChange类来获取对象的属性变化。PropertyChange类包含了属性的名称、旧值和新值等信息。
  3. compare方法中,根据需要比较的字段值,使用PropertyChange对象提供的方法来获取旧值和新值,并进行比较。
  4. 在比较器类中,您还可以实现其他自定义逻辑,例如忽略某些属性的比较或者自定义比较规则。
  5. 将自定义比较器应用到您的对象比较中。您可以通过Javers的JaversBuilder类创建一个Javers实例,并使用registerCustomComparator方法注册您的自定义比较器。

下面是一个示例代码,展示了如何使用Javers的自定义比较器来根据字段值进行比较:

代码语言:java
复制
import org.javers.core.diff.changetype.PropertyChange;
import org.javers.core.metamodel.object.GlobalId;
import org.javers.core.metamodel.property.Property;
import org.javers.core.metamodel.type.ValueObjectType;
import org.javers.core.metamodel.type.ValueType;
import org.javers.core.metamodel.type.TypeMapper;
import org.javers.core.diff.custom.CustomPropertyComparator;

public class FieldValueComparator implements CustomPropertyComparator {

    @Override
    public boolean equals(Object leftValue, Object rightValue, Property property) {
        // 根据需要比较的字段值进行比较逻辑
        // 返回true表示相等,返回false表示不相等
        // 可以使用leftValue和rightValue进行比较
        // 可以使用property.getName()获取属性名称
        // 可以使用property.getType()获取属性类型
        // 可以使用property.getGenericType()获取属性泛型类型
        // 可以使用property.getGenericType().getActualTypeArguments()获取泛型类型参数
        // 可以使用property.getGenericType().getRawType()获取原始类型
        // 可以使用property.getGenericType().getActualTypeArguments()[0]获取第一个泛型类型参数

        // 示例:比较两个字符串属性是否相等
        if (leftValue instanceof String && rightValue instanceof String) {
            return leftValue.equals(rightValue);
        }

        // 示例:比较两个整数属性是否相等
        if (leftValue instanceof Integer && rightValue instanceof Integer) {
            return ((Integer) leftValue).equals((Integer) rightValue);
        }

        // 其他类型的比较逻辑...

        return false;
    }
}

然后,您可以将自定义比较器应用到您的对象比较中,示例如下:

代码语言:java
复制
import org.javers.core.Javers;
import org.javers.core.JaversBuilder;

public class Main {
    public static void main(String[] args) {
        // 创建Javers实例
        Javers javers = JaversBuilder.javers().registerCustomComparator(new FieldValueComparator()).build();

        // 比较对象
        MyObject oldObject = new MyObject("value1");
        MyObject newObject = new MyObject("value2");
        Diff diff = javers.compare(oldObject, newObject);

        // 输出差异
        System.out.println(diff);
    }
}

这样,您就可以使用Javers根据字段值而不是ID/对象引用进行比较了。

请注意,以上示例中的MyObject是一个自定义的Java对象,您需要根据自己的实际情况进行调整。

希望这个答案能够满足您的需求。如果您需要更多关于Javers或其他云计算领域的问题,请随时提问。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

.Net面试经验总结(.NetC#)

接口可以作用于类型和引用类型;抽象类只能作用于引用类型。例如,Struct就可以继承接口,不能继承类。...引用类型变量的赋值只把对象引用的指针赋值给变量,使得变量引用对象共享同一个内存地址。 继承区别:类型不能派生出新的类型:所有的类型均隐式派生自 System.ValueType。...类型传递的是的副本,引用类型传递的是对象引用,所以值参数的修改不影响原始引用类型的修改影响原始; C#中使用StringBuilder拼接字符串时有何优点 StringBuilder是动态对象...,允许扩充他所封装的字符串中的字符数量,在生成string对象之前,不会产生任何string对象,所以在进行大量的字符串拼接或者频繁的堆某一个字符串进行操作时最好使用StringBuilder,不要使用...什么叫Sql注入,如何防止? 答: 用户根据系统的程序构造非法的参数从而导致程序执行不是程序员期望的恶意SQL语句。使用参数化的SQL就可以避免SQL注入。

1.7K52

Q查询和F查询

通过 Django 的 F() 类,Python 所做的就是创建 SQL 语法来引用这个字段并描述操作。...,不是 Python 来完成工作; 减少某些操作所需的查询次数。...避免竞争 F() 的另一个有用的好处是,数据库——不是 Python——更新一个字段,避免了 竞争条件。...如果数据库负责更新字段,那么这个过程就比较稳健:它只会在执行 save() 或 update() 时,根据数据库中字段来更新字段不是根据检索实例时的来更新。...根据字段进行查询 F() 在 QuerySet 过滤器中也非常有用,它们可以根据对象字段不是 Python 的标准来过滤一组对象。F()能将模型字段与同一模型中的另一字段比较

1.3K10

Oracle数据库的几种设计规范

通过设置默认的形式,来避免空字段的产生,如一个商城VIP系统,有的时候身份证号字段可以为空,因为不是每个人都能记得住身份证号的,办理业务时身份证没带身上不能及时提供,因此身份证号码字段可以为空,满足这些特殊需求...表中记录应该有一个标识符 在数据库表设计的时候,数据库管理员就应有个好习惯,用一个ID号码 标识进行记录,不是通过名字 编号等字段对记录进行区分,每个表都应该有一个id任何两个记录都不能共用一个id...另外 这个id最好有数据库来进行自动管理,不要吧这个任务给前台应用程序,否则 很容易产生id不统一的情况 4....数据库对象要有统一的前缀名 一个比较复杂的应用系统,其对应的数据表往往数以千计,钥匙数据库管理员看到对象名就了解这个数据库对象所起的作用 这样比较困难,而且在数据库对象引用的时候,数据库管理员也会为不能迅速找到数据对象对发愁...为此在开发数据库之前,最好花时间去制定一个数据库的对象的前缀命名规范, 如在设计数据库时和前台应用程序协商,确定合理的命名规范,如和物料管理模块相关的表可以用M为前缀,订单管理相关的就用C作为前缀,具体采用什么前缀就根据用户的爱好

1.2K20

小师妹问我:Mybatis常见注解有哪些?

在应用层手动指定主键 手动指定的方式不把主键区别看待,插入之前在应用层生成对象的时候就会给主键一个,插入的时候与普通字段没啥区别。...update(User user); @Select 查询的时候稍稍有些复杂,因为查询会涉及到如何将查出来的字段设置到对象上,对应xml文件中的标签。...其他注解 @Results:结果映射的列表, 包含了一个特别结果列如何被映射到属性或字段的详情。属 性:value, id。value 属性是 Result 注解的数组。...id 属性是一个布尔,表 示了应该被用于比较(和在 XML 映射 中的相似)的属性。...属性: id,column,javaType,typeHandler。id 属性是布尔, 来标识用于比较的属 性,和XML 元素相似。对应xml中的标签。

1.3K10

HashMap 的实现原理

我们这个类中有个字段ID,那么我们就定义我们的 hashcode 为 ID%8,然后把我们的类存放在取得得余数那个位置。...但是如果两个类有相同的 hashcode 怎么办那(我们假设上面的类的 ID 不是唯一的),例如 9 除以 8 和 17 除以 8 的余数都是 1,那么这是不是合法的,回答是:可以这样。...关于 equals equals 和 == == 用于比较引用比较基本数据类型时具有不同的功能。...比较基本数据类型,如果两个相同,则结果为 true,而在比较引用时,如果引用指向内存中的同一对象,结果为 true。 equals() 作为方法,实现对象比较。...但是 new HashMap(1024) 还不是更合适的,因为 0.75*1000 1000, 我们必须这样 new HashMap(2048

28010

Vue 的响应式机制就是个“坑”?

我这里聊的可不是带有强制输入的嵌套引用,那明显更复杂、更混乱。只有对一切了然于胸的大师才能解决这类问题,所以本文暂且不表。...理由也不复杂:我们以参数形式收到的 notification 对象很可能是个普通的 JS 对象,而在数组中该条目是个 Proxy。 那该如何处理?...== deep.value (重用为该目标创建的 reactive ) 现在来看第二个条目 ,根据 shallowRef 的或者直接根据 raw 进行创建: const list = ref([shallow.value...更好的办法,应该是尝试添加唯一标识符、ID、UUID,或者使用可以安全比较的现有条目唯一原始。...如果大家(出于某种原因)需要用 == 来比较对象实例,请使用 toRaw 以确保实际比较的是普通 JS 对象。只要可能,最好只比较原始唯一,例如 ID 或者 UUID。

6710

【DDD】持久化领域对象的方法实践

觉得持久化为表的原因是 数据表模型并不代表代码层面的模型,代码里面的对象其实并没有ID的说法,所以它是符合对象的,持久化为字段的话,同一个对象数据会被复制为多份导致数据冗余。...应该站在客观的角度,实际的项目需要哪种手段就根据切实的情况来选择。 来说一下持久化为字段的情况 该手段其实在近期来说比较流行,特别是在EFCore2.0之后,为什么呢?...持久化模型的设计在于您自己,您可以根据数据库的情况任意更改,您只需保证它能和真正的领域对象完成映射就可以了。...Table 1 方案 优点 缺点 持久对象到表字段 数据依附于某条实体或者聚合根 数据冗余、会表拥有太多字段 持久化对象到表 数据量不冗余 会存在许多表、从数据库层面很难看出它和实体的区别 Table...配置规则可能比较繁琐,有时候为了领域模型适配数据改动领域模型 总结 该篇文章文字比较多,也许花费了您太长的时间阅读,但希望本文的这些方案能够对您持久化领域对象有所帮助。

1.6K30

流畅的 Python 第二版(GPT 重译)(三)

通常使用is运算符进行身份检查,该运算符比较对象ID,因此我们的代码不需要显式调用id()。接下来,我们将讨论is与==的区别。...如果引用在不同的上下文中—比如不同的堆栈帧—使用is运算符可能不可行。 选择==和is之间 ==运算符比较对象(它们持有的数据),is比较它们的身份。...在编程时,我们通常更关心对象不是对象的身份,因此在 Python 代码中,==比is出现得更频繁。 但是,如果您要将变量与单例进行比较,则使用is是有意义的。...换句话说,元组的不可变性实际上是指tuple数据结构的物理内容(即它保存的引用),不是扩展到所引用对象。 示例 6-5 说明了元组的因所引用的可变对象的更改发生变化的情况。...现在应该清楚了,浅复制很容易实现,但可能并不是你想要的。如何进行深复制是我们下一个话题。 任意对象的深复制和浅复制 使用浅复制并不总是问题,但有时你需要进行深复制(即不共享嵌入对象引用的副本)。

5900

白话解析Java中HashMap底层实现原理

) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里“ 再归纳一下就是hashCode是用于查找使用的,equals是用于比较两个对象的是否相等的。...我们这个类中有个字段ID,那么我们就定义我们的hashcode为ID%8,然后把我们的类存放在取得得余数那个位置。...2.但是如果两个类有相同的hashcode怎么办那(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?...: 比较基本数据类型,如果两个相同,则结果为true 而在比较引用时,如果引用指向内存中的同一对象,结果为true; equals()作为方法,实现对象比较。...但是new HashMap(1024)还不是更合适的,因为0.75*1000 1000, 我们必须这样new HashMap(2048)才最合适

58310

equals和hashCode你学会了么?

非空性 非空性要求所有的对象不等于null 如何写好equals 如果比较操作昂贵,可以优先使用==操作符检查是否是同一个对象引用 使用instanceOf操作符检查参数是否为正确的类型(正确的类型通常是指...equals方法所在的那个类,但有时也是该类实现的某个接口,比如Set、List等集合) 把参数转换为正确的类型 对于该类中的每个关键字段,检查参数中的字段是否与该对象中对应的字段相匹配,对于既不是float...也不是double类型的基本类型域,可以使用==操作符进行比较,对于引用类型可以递归调用equals方法,对于float使用Float.compare方法,double使用Double.compare方法...如果两个对象根据equals方法比较结果是相等的,那么调用任意一个对象的hashCode方法都必须产生相同的结果 如果两个对象根据equals方法比较结果不想等,那么调用这两个对象的hashCode方法可以产生相同或者不同的整数结果...如果是一个引用类型,递归调用hashCode 如果是是一个数组,调用Arryas.hashCode方法 如果一个类是不可变的并且计算散列码的成本比较大,可以考虑把散列码缓存在对象内部,不是每次请求时都重新计算

70720

搞定Mybatis面试题

当实体类中的属性名和表中的字段名不一样 ,怎么办? 第一种, 通过在查询的 SQL 语句中定义字段名的别名,字段名的别名和实体类的属性名一致。...好处是只发一个 SQL 查询,就可以把主对象和其关联对象查出来,坏处是 SQL 可能比较复杂。 那么问题来了,join 查询出来 100 条记录,如何确定主对象是 5 个,不是 100 个呢?...Mybatis 会根据来完成 100 条记录的去重复功能, 可以有多个,代表了联合主键的语意。 同样主对象的关联对象,也是根据这个原理去重复的。...Mybatis 去重复处理后,结果为 1 个老师和 6 个学生,不是 6 个老师和 6 个学生。...Mybatis 是如何进行分页的?分页插件的原理是什么? Mybatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非数据库分页。

1.2K30

JAVA中Swagger产出更加符合我们诉求的描述文档,按需决定显示或者隐藏指定内容

在前一篇文档《JAVA中自定义扩展Swagger的能力,自动生成参数取值含义说明,提升开发效率》中,我们探讨了如何通过自定义注解的方式扩展swagger的能力Swagger支持自动从指定的枚举类生成接口文档中的字段描述的实现思路...更改接口文档总标题与描述 默认的情况下,Swagger的界面整个文档的名称以及描述内容都是通用,这会人拿到文档之后比较困惑,无法知晓这是哪个项目哪个系统哪个服务提供的接口,也不知道接口是哪个团队负责...这个时候,就需要按照package进行白名单控制的能力了。swagger还支持根据给定的basePackage以及paths进行组合控制,仅显示给定包下指定路径下的接口。...在上面的例子中: 作为数据表实体类进行逻辑处理的时候,需要用到唯一主键id信息 作为recordOperateLog接口的请求Body体时,调用方是不需要指定这条记录的ID的(ID会在存储到DB的时候自动由...DB生成唯一自增主键) 这种场景下,我们就希望提供出去的接口文档中,在对recordOperateLog接口的请求body体中字段说明的时候,就不要体现出id字段,避免调用方产生疑惑,不知道id调用的时候应该如何赋值

2.2K10

“禁止用 select * 作为查询字段列表”落地指南

【2】定义新的 DO 对象 >: 1)可以根据方法名和返回,明确感知当前业务获取的字段 2)专用查询和通用查询很好地作区分 >: 当场景较多时,需要定义的 DO 对象过多...ID 进行查询。...如 > 骑手送菜的场景,此时对于当前订单而言,只应该送给你订单对应数量的蔬菜,不是把超市所有菜都带来,送到你家门口时,再全部摆出来,你现场自己数。...【2】如果你依赖的二方服务给你返回一个全的 DTO,根据调用的方法名去“猜测” 里面哪些属性会被赋值(不看他的源码,你咋知道哪些被赋值哪些没有被赋值),是不是很可怕?...可是,有什么能比参数和返回来约定更合适呢? 后面任何改动都要去增删文档? 人员变动之后代码如何维护?

1K20

“禁止用 select * 作为查询字段列表”落地指南

【2】定义新的 DO 对象 >: 1)可以根据方法名和返回,明确感知当前业务获取的字段 2)专用查询和通用查询很好地作区分 >: 当场景较多时,需要定义的 DO 对象过多...ID 进行查询。...如 > 骑手送菜的场景,此时对于当前订单而言,只应该送给你订单对应数量的蔬菜,不是把超市所有菜都带来,送到你家门口时,再全部摆出来,你现场自己数。...【2】如果你依赖的二方服务给你返回一个全的 DTO,根据调用的方法名去“猜测” 里面哪些属性会被赋值(不看他的源码,你咋知道哪些被赋值哪些没有被赋值),是不是很可怕?...可是,有什么能比参数和返回来约定更合适呢? 后面任何改动都要去增删文档? 人员变动之后代码如何维护?

93510

C#类型基础

上面a、b指向的显然是不同的对象,只是对象包含的相同,所以可见,对于string类型,CLR对它们的比较实际上比较的是不是引用。...我们定义一个新的结构Line,它代表直线上的线段,我们它的一个成员为类型ValPoint,一个成员为引用类型RefPoint,然后去作比较。...对 堆上对象 的成员(字段)进行一对一的比较,而成员又分为两种类型,一种是类型,一种是引用类型。...此时,如果已经有了一个对象,再创建新对象时,可能会采用复制现有对象的方法,不是重新建一个新的对象。本节就讨论如何进行对象的复制。...当我们对对象进行一个浅度复制的时候,对于类型成员,会复制其本身(类型变量本身包含了所有数据,复制时进行按位拷贝);对于引用类型成员(注意它会引用另一个对象),仅仅复制引用不创建其引用对象

85730

代码重构(三):数据重构规则

引用对象正好相反,一个内存区域被多个引用指针所引用,这些引用指针即为引用对象,因为多个指针指向同一块内存地址,所以无论你改变哪一个指针中的,其他引用对象也会跟着变化。...基于对象引用对象的特点,我们有时候根据程序的上下文和需求需要将一些类型改变成引用类型。因为有时候需要一些类的一些对象在应用程序中唯一。...不过此时的引用对象是从Customer中获取的,不是外部传过来的。下方是Order类中对工厂方法的调用,这样做的好处就是,我们只对模块的内部进行了修改,测试用例无需修改。...至于如何对“==” 运算符进行重载就不做过多的赘述了,因为该知识点不是本篇博客的重点。...今天博客中的该部分是分层的微观的东西,也就是具体如何将业务逻辑从GUI中进行剥离。所以在接下来的实例中是和UI实现有关的,会根据一个比较简单的Demo来一步步的将UI中的业务逻辑进行分离。

94610

代码重构(三):数据重构规则

引用对象正好相反,一个内存区域被多个引用指针所引用,这些引用指针即为引用对象,因为多个指针指向同一块内存地址,所以无论你改变哪一个指针中的,其他引用对象也会跟着变化。...基于对象引用对象的特点,我们有时候根据程序的上下文和需求需要将一些类型改变成引用类型。因为有时候需要一些类的一些对象在应用程序中唯一。...不过此时的引用对象是从Customer中获取的,不是外部传过来的。下方是Order类中对工厂方法的调用,这样做的好处就是,我们只对模块的内部进行了修改,测试用例无需修改。 ?  ...至于如何对“==” 运算符进行重载就不做过多的赘述了,因为该知识点不是本篇博客的重点。...今天博客中的该部分是分层的微观的东西,也就是具体如何将业务逻辑从GUI中进行剥离。所以在接下来的实例中是和UI实现有关的,会根据一个比较简单的Demo来一步步的将UI中的业务逻辑进行分离。

1.2K60

.Net中的反射(序章) - Part.1

,将Value设为Id字段。...),然后根据状态在数组中的位置来给对象的属性赋值。...现在假设我们需要比较两个对象是否相等。当我们比较两个引用类型的变量是否相等时,我们比较的是这两个变量所指向的是不是堆上的同一个实例(内存地址是否相同)。当我们比较两个类型变量是否相等时,怎么做呢?...因为变量本身就包含了类型所有的字段(数据),所以在比较时,就需要对两个变量的字段进行逐个的一对一的比较,看看每个字段是否都相等,如果任何一个字段不等,就返回false。...前面我们已经提到如果是类型,会对两个变量的字段进行逐个的比较,看看每个字段是否都相等,但是如何获取变量的所有字段,遍历字段,并逐一比较呢?

1.2K40

阿里华为等大厂架构师如何解决空指针问题

NPE事发场景 参数是Integer等包装类,自动拆箱时 字符串比较 如ConcurrentHashMap这种不支持K.V为null的容器 A对象含B对象,通过A对象字段获得B对象后,没有判空B就调用...+1 对入参String s进行比较,判断内容是否为"OK" 对入参String s、t进行比较,判断是否相等 对new出的ConcurrentHashMap进行put,Key和Value都设为null...对程序来说,null就是指针没有任何指向,结合业务逻辑情况就复杂得多,需考虑: DTO中字段的null到底意味着什么?是客户端没传给这个字段? 既然空指针很讨厌,那么DTO中的字段要设默认吗?...如果不传,那么Optional本身为null,直接跳过Entity字段的更新即可,这样动态生成的SQL就不会包含这个列;如果传了,那么进一步判断传的是不是null。...原因是: MySQL中sum函数没统计到任何记录时,会返回null不是0,可以使用IFNULL函数把null转换为0 MySQL中count字段不统计null,COUNT(*)才是统计所有记录数量的正确方式

1.1K30

3分钟快速阅读-《Effective Java》(一)

简介 Effective Java这本书针对的是有经验的程序员,本书共计78个条目,目的是告诉大家如何进行更加有效的编程 1.考虑用静态工厂方法代替构造器 静态工厂方法的优点 1.1 静态工厂方法有对应方法名称...静态工厂方法的缺点 1.1 如果不含有公有的或者受保护的构造器,就不能被子类化 1.2 本质上跟其他静态方法没有太大区别 2.遇到多个构造器参数时考虑使用构建器 当一个对象字段很多,那么需要实例化时如果每种不同的对象都写一个对象的构造器来进行实例化会使得代码十分冗余...,如果使用无参构造器,然后使用setter方法来给每个字段设置,会导致这个对象字段可变且不安全,所以需要考虑使用构建器.构建器代码如下所示 // 工厂实例类代码 public class FactoryDemo...B,当类A进行实例化对象A时,可以考虑使用静态代码块来对关联对象B进行初始化,避免每次调用对象A时都会初始化一次对象B 备注:以上所说的情况仅仅只是针对于需求当中该对象是只需要被初始化一次,后续不需要再进行更改的情况下可以使用...时总要覆盖hashCode 摘自Object规范[JavaSE6]第二条: 如果两个对象根据equals(Object)方法比较是相等的,那么调用这两个对象中任意一个对象的hashCode方法都必须产生同样的整数结果

36510
领券