休み、怠zyな負荷、プロキシ、継承
-
27-10-2019 - |
質問
継承を扱う際に、冬眠の怠zyな負荷に問題があります。サブクラス化された2番目のエンティティを参照するエンティティが1つあります。参照を怠lazにロードしたいのですが、これにより.equals()メソッドにエラーが発生します。
以下のコードでは、Aのインスタンスでequals()を呼び出すと、オブジェクトOがCのインスタンスであるかどうかを確認するときにC.Equals()関数でチェックが失敗します。 Cではなくbを拡張するJavassistによって作成されたプロキシ
Hibernateは、データベースにアクセスして怠zyな負荷を破らずにタイプCのプロキシを作成できないことを理解しています。クラスAのgetB()関数をプロキシ(怠laz)の代わりにコンクリートBインスタンスを返すようにする方法はありますか? hibernate固有の@lazytoone(lazytooneoption.no_proxy)getb()メソッドで注釈を使用してみました。
@Entity @Table(name="a")
public class A {
private B b;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="b")
public B getB() {
return this.b;
}
public boolean equals(final Object o) {
if (o == null) {
return false;
}
if (!(o instanceof A)) {
return false;
}
final A other = (A) o;
return this.getB().equals(o.getB());
}
}
@Entity @Table(name="b")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="type",
discriminatorType=DiscriminatorType.STRING
)
public abstract class B {
private long id;
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof B)) {
return false;
}
final B b = (B) o;
return this.getId().equals(b.getId());
}
}
@Entity @DiscriminatorValue("c")
public class C extends B {
private String s;
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (obj == null) {
return false;
}
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof C)) {
return false;
}
final C other = (C) o;
if (this.getS() == null) {
if (other.getS() != null) {
return false;
}
} else if (!this.getS().equals(other.getS())) {
return false;
}
return true;
}
}
@Entity @DiscriminatorValue("d")
public class D extends B {
// Other implementation of B
}
解決
@lazytoone(lazytooneoption.no_proxy)注釈を使用しようとして、私は正しい追跡にいたことがわかりました。 Hibernate Bytecode Enhancerツールをまだ実行していなかったため、箱から出していませんでした。これの指示はこちらにあります:
他のヒント
変更を試してみたいと思うかもしれません fetch
getb()toのプロパティ FetchType.EAGER
. 。お役に立てれば。
オブジェクトがエンティティであり、怠zyなロードであるかどうかに関係なく、平等の契約を尊重し、インスタンスを使用するサブクラスに等しい専門化を持つことは事実上不可能です。確かに、あなたはあなたが持っているでしょう b1.equals(c1) == true
, 、 しかし c1.equals(b1) == false
.
したがって、すべてのサブクラスが基本クラスを使用する必要があるため、スーパークラス(b)は平等を定義し、最終的にする必要があると思います。 equals
方法。
とはいえ、Bのあなたの等しい方法は正しくありません:
if (!super.equals(obj)) {
return false;
}
これは、2つのbインスタンスを等しくするために、equalsのオブジェクト実装がtrueを返す必要があることを意味します。つまり、2つのBインスタンスは同じオブジェクトである場合にのみ等しくなります。
if (!(obj instanceof C)) {
return false;
}
Bクラスが他のインスタンスがCのインスタンスであることを確認するのはなぜですか?他のインスタンスがBのインスタンスであるかどうかを確認する必要があります。
最終的には、2つのBSが同じIDを持っている場合、およびIDはすべての継承ツリーに対して一意でなければならないため、これを最終的に等しくする場合は安全です。