我在#hibernate
IRC 上,有人与我分享了以下(部分)模式
@Entity
public MyEntity() {
... primary key, object properties, getters/setters go here ...
@Column(nullable=false)
private int hashCode;
public MyEntity() {
hashCode += id;
}
private final Set<String> tags = Sets.newHashSet();
public void addTag(String tag) {
if(tags.add(tag)) {
hashCode += tag.hashCode();
}
}
public void removeTag(String tag) {
if(tags.remove(tag) {
hashCode -= tag.hashCode();
}
}
public void hashCode() {
return hashCode;
}
... http://www.artima.com/lejava/articles/equality.html style equals ...
}
可以将其称为“分段更新的缓存 hashCode”。(这绝对不是一些评论者认为的“业务密钥”模式。“业务密钥”模式需要一个具有唯一性约束的列,例如用于相等性测试的用户名)。
在 JPA/Hibernate 中使用时,这意味着can 具有与JBoss Equals 和 HashCode 文章@Entity
中的“eq/hC with buisness [sic] key”类似的优势,但其行为方式与开发人员期望的任何普通 Javabean 对象的行为方式相同(即不必像数据库行一样考虑对象):在持久化到数据库之前;在获取模式之后;并随时在 a或模式中使用fetch 。Transaction
EAGER
LAZY
Transaction
EXTENDED
但是,确保hashCode
始终正确更新可能是一个真正的挑战。
这里有没有人对这种模式有任何经验,你能分享你对它的发现(积极的和消极的)吗?我对 Gotchas 非常感兴趣,但我对那些声称某些东西“不好”的评论完全不感兴趣,而没有关于它为什么不好的可靠论据。
请注意,我知道The JPA hashCode() / equals() dilemma,但我不相信该模式实际上已包含在该讨论中。
最初建议使用此模式作为Collection
在 s 中加载嵌套 s时避免问题的一种方法@Entity
,例如在带有 EAGER @ElementCollection 的 find() 上的 Hibernate LazyInitializationException中遇到的问题。
更新:一些评论者对现有方法充满热情。为免生疑问,我只是对这种新模式的优点感兴趣。供您参考,也请您不要再说您认为应该如何实现 equals/hashCode,请注意,我已经为我@Entity
的 s 使用了以下模式好几年了:
@Id
private UUID id = UUID.randomUUID();
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof MY_CLASS) || id == null)
return false;
MY_CLASS other = (MY_CLASS) obj;
return id.equals(other.id);
}
@Override
public int hashCode() {
Preconditions.checkNotNull(id, "id must be set before @Entity.hashCode can be called");
return id.hashCode();
}
而且我最近才尝试了一些新方法,看看我是否真的需要像这样的单独方法
public boolean hasSameProperties(Note other) {
Preconditions.checkNotNull(other);
if (this == other)
return true;
return Objects.equal(source, other.source)
&& Objects.equal(title, other.title)
&& Objects.equal(tags, other.tags)
&& Objects.equal(contents, other.contents);
}