私は#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 で使用すると、 JBoss Equals and HashCode 記事@Entity
の「ビジネス [sic] キーを使用した eq/hC」と同様の利点があり、開発者が通常の Javabean オブジェクトの動作を期待する方法で動作することを意味します (つまり、データベース行のようなオブジェクトについて考える必要はありません): DB に永続化される前。取得モードの後。およびモード内またはモードでいつでもフェッチできます。Transaction
EAGER
LAZY
Transaction
EXTENDED
ただし、hashCode
が常に正しく更新されていることを確認することは、実際の課題になる可能性があります。
このパターンを経験したことがある人はいますか? それについての発見 (ポジティブとネガティブの両方) を共有できますか? 私は Gotchas に非常に興味がありますが、なぜそれが悪いのかについて確固たる議論なしに何かが「悪い」と主張するコメントにはまったく興味がありません.
私はJPA hashCode() / equals() ジレンマを認識していますが、このパターンが実際にその議論でカバーされているとは思わないことに注意してください。
このパターンは当初、EAGER @ElementCollection を使用した find() での Hibernate LazyInitializationException で発生するような、ネストされたCollection
s をs にロードする際の問題を回避する方法として提案されました。@Entity
更新: 一部のコメンターは、既存のアプローチに非常に熱心になっています。誤解を避けるために、私はこの新しいパターンのメリットにのみ興味があります。ご参考までに、また、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);
}