鉴于我的特定使用模式,我试图找出这种方法有什么问题:
@Entity
public class DomainObject {
@Id // + sequence generator
private Long id;
@Override
public boolean equals(Object o) {
// bunch of other checks omitted for clarity
if (id != null) {
return id.equals(o.getId());
}
return super.equals(o);
}
@Override
public int hashCode() {
if (id != null) {
return id.hashCode();
}
return super.hashCode();
}
我已经阅读了有关该主题的几篇文章,听起来您不想在 equals/hashCode 中使用 DB 生成的序列值,因为在对象被持久化并且您不想要不同的瞬态之前它们不会被设置实例都相等,否则持久层本身可能会中断。
但是,回退到瞬态对象的默认 Object equals/hashCode(实例相等)然后在你拥有它时使用生成的 @Id 有什么问题吗?
我能想到的最糟糕的事情是,瞬态对象永远不能等于持久对象,这在我的用例中很好 - 我唯一一次将对象放入集合中并且想要contains
工作,所有对象已经持久化并且都有 ID。
但是,我觉得在持久层深处以一种非常微妙、不明显的方式存在其他问题,但我无法弄清楚是什么。
其他选项似乎也不那么吸引人:
什么都不做,并且使用实例相等(默认 Object.equals):对我的大多数实体都很好,但是当我想要一个包含分离实体的集合(例如,会话范围)和当前交易中的“实时”交易
使用业务键:我有明确的自然键,但它们是可变的,这将有一些与上述相同的问题(如果对象更改,哈希码稳定性)
使用 UUID - 我知道这会起作用,但感觉用工件污染数据库以支持 java.util 集合是错误的。
也可以看看: