【发布时间】:2012-11-12 02:20:18
【问题描述】:
鉴于我的特定使用模式,我正试图找出这种方法有什么问题:
@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):适用于我的大多数实体,但是当我想要一个包含多个分离实体的集合时,我厌倦了少数情况下的解决方法(例如,会话范围)和当前事务中的“实时”范围
使用业务密钥:我有明确的自然密钥,但它们是可变的,这将有 一些与上面相同的问题(如果对象发生变化,hashCode 稳定性)
使用 UUID - 我知道这会起作用,但是用支持 java.util 集合的工件污染数据库感觉不对。
另见:
【问题讨论】: