java - 为什么 session 之外的 Hibernate 实体应该实现 equals() 和 hashcode() ?

标签 java hibernate orm equals hashcode

部分2.1.5 Hibernate 用户指南指出

In cases where you will be dealing with entities outside of a Session (whether they be transient or detached) ... you should consider implementing equals/hashCode.

忽略在集合(例如 Set)中使用这些实体的明显原因,我们希望或需要按照 hibernate 文档中的建议覆盖现有的 equals/hashcode 的其他情况是什么?

最佳答案

首先,实体平等是一个领域细节,最好从业务代码中抽象出来。显然,最好的地方是实体本身。此外,相等规则通常可能会根据实体状态或其他域规则而变化,因此重写 equals 方法可确保这些规则不仅在业务代码中得到遵守,而且在集合使用和 Hibernate 的 session 管理中也得到遵守。

考虑一个基于组合键的实体,它使用多个字段来构成相等性。以下哪项业务代码看起来更有吸引力并且更改起来最不严格:

public void someBusinessFunction(EntityA e1, EntityA e2) {
  if(e1.equals(e2))
    throw new SomeEqualityException();
  // do logic
}

public void someBusinessFunction2(EntityA e1, EntityA e2) {
  if(e1.getId().getFieldA().equals(e2.getId().getFieldA()) &&
       e1.getId().getFieldB().equals(e2.getId().getFieldB()) &&
       e1.getId().getFieldC().equals(e2.getId().getFieldC())) {
    throw new SomeEqualityException();
  }
  // do logic
}

从业务代码的角度来看,我们不应该关心什么构成平等。代码只关心同一类的两个实例是否彼此相等。使用什么规则来确定用例是不相关的。

简而言之,通过抽象首先应该抽象的细节来实现良好的编程。

编辑

更具体地说,对于 Java 语言本身,Object 的普通相等性仅通过 == 运算符比较两个操作数是否指向同一物理实例。仅当两个实例指向同一内存位置时,这才有效。

可以通过多个事务获取相同的域实体,因此会指向两个不同的内存位置,因为它们曾经由不同的 session 管理。在这种情况下,默认的 equals 方法将返回 false,这可能是不需要的。

通过重写 equals 方法,您可以显式确保上述情况始终返回 true 以获得相等性,无论实例如何获取以及存储在何处内存中。

此外,java 文档明确指出,当您重写 equals 以维护 hashCode 之间的契约时,应该重写 hashCode equals 这样,当对象相等时,哈希码也相等。

关于java - 为什么 session 之外的 Hibernate 实体应该实现 equals() 和 hashcode() ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34533688/

相关文章:

java.lang.IllegalStateException : Failed to introspect Class 错误

java - 为什么groovy给每个类添加打印方法?

java - 处理 DBUnit 中的保留字符

java - 一对一连接表级联删除

hibernate - Coldfusion 10 ORM "Error while resolving the relationship"

orm - sequelize中allowNull和require的区别

Java File 到 ArrayList 并将 ArrayList 引用到另一个类

java - 使用标记列表构建抽象语法树

java - 为什么 JPA 实体在 rowKey 属性为主键时抛出异常?

java - 计划的 Spring MVC 任务不更新数据库实体