3

継承を処理するときに、休止状態での遅延読み込みに問題があります。サブクラス化された2番目のエンティティを参照する1つのエンティティがあります。参照を遅延ロードしたいのですが、これにより.equals()メソッドでエラーが発生します。

以下のコードでは、Aのインスタンスでequals()を呼び出すと、オブジェクトoがCのインスタンスであるかどうかをチェックするときに、C.equals()関数でチェックが失敗します。他のオブジェクトが実際には休止状態であるため失敗します。 javassistによって作成されたプロキシ。CではなくBを拡張します。

Hibernateは、データベースにアクセスして遅延読み込みを中断しない限り、タイプCのプロキシを作成できないことを理解しています。クラスAのgetB()関数がプロキシの代わりに具象Bインスタンスを(怠惰に)返すようにする方法はありますか?getB()メソッドでHibernate固有の@LazyToOne(LazyToOneOption.NO_PROXY)アノテーションを使用してみましたが、役に立ちませんでした。

@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
}
4

3 に答える 3

1

@LazyToOne(LazyToOneOption.NO_PROXY)アノテーションを使用しようとして、私は正しい追跡を行っていたことがわかりました。Hibernateバイトコードエンハンサーツールをまだ実行していないため、箱から出してすぐには機能しませんでした。このための手順はここにあります:

19.1.7。レイジープロパティフェッチの使用

于 2012-01-12T15:19:00.370 に答える
0

fetchgetB()のプロパティをに変更してみてくださいFetchType.EAGER。お役に立てれば。

于 2012-01-11T16:52:09.070 に答える
0

オブジェクトがエンティティであるか、遅延ロードされているかどうかに関係なく、equalsのコントラクトを尊重し、instanceofを使用するサブクラスでequalsを特殊化することは事実上不可能です。確かに、あなたはあなたが持っているであろう状況になりますb1.equals(c1) == true、しかしc1.equals(b1) == false

したがって、すべてのサブクラスは基本クラスのメソッドを使用する必要があるため、スーパークラス(B)はequalsを定義し、それをfinalにする必要があると思いますequals

そうは言っても、Bのequalsメソッドは正しくありません。

if (!super.equals(obj)) {
   return false;
}

これは、2つのBインスタンスを等しくするには、equalsのオブジェクト実装がtrueを返す必要があることを意味します。つまり、2つのBインスタンスは、同じオブジェクトである場合にのみ等しくなります。

if (!(obj instanceof C)) {
    return false;
}

Bクラスが他のインスタンスがCのインスタンスであることを確認するのはなぜですか。他のインスタンスがBのインスタンスであるかどうかを確認する必要があります。

最終的に、2つのBが同じIDを持っている場合は等しく、IDはすべての継承ツリーで一意である必要があるため、このequalsメソッドをfinalにすると安全です。

于 2012-01-11T16:53:58.703 に答える