我当时在#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 ...
}
人们可以将其称为“分段更新的缓存哈希码”。 (这绝对是NOT正如一些评论者似乎相信的那样,这是一种“业务关键”模式。 “业务键”模式需要一个具有唯一性约束的列,例如用户名,用于相等性测试)。
当在 JPA/Hibernate 中使用时,这意味着@Entity
can 具有与“eq/hC with buisness [sic] key”类似的优点JBoss Equals 和 HashCode 文章 https://community.jboss.org/wiki/EqualsAndHashCode,但其行为方式与开发人员期望的任何普通 Javabean 对象的行为方式相同(即不必将对象视为数据库行):在持久化到数据库之前;之后Transaction
in EAGER
获取模式;并随时与LAZY
获取内部aTransaction
or in EXTENDED
mode.
然而,确保hashCode
始终正确更新可能是一个真正的挑战。
这里有人对这种模式有任何经验吗?您能分享一下您对此的发现(积极的和消极的)吗?我对陷阱非常感兴趣,但我对那些声称某件事是“坏”而没有坚实的论据说明为什么它不好的评论完全不感兴趣。
请注意,我知道JPA hashCode() / equals() 困境 https://stackoverflow.com/questions/5031614,但我不认为该讨论实际上涵盖了这种模式。
这种模式最初被建议作为避免加载嵌套时出现问题的一种方法Collection
s in @Entity
s,比如遇到Hibernate LazyInitializationException on find() 与 EAGER @ElementCollection https://stackoverflow.com/questions/11604370.
更新:一些评论者对现有方法变得非常热情。为了避免疑问,我只是对这种新模式的优点感兴趣。供您参考,并要求您停止说您认为应该如何实现 equals/hashCode,请注意,我在我的代码中使用了以下模式@Entity
已经好几年了:
@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);
}