8

ポリモーフィズムがサポートされるように、Hibernateオブジェクトのプロキシを解除するにはどうすればよいですか?

次の例を考えてみましょう。クラスAとBは2つの休止状態のエンティティです。Bには2つのサブタイプCとDがあります。

List<A> resultSet = executeSomeHibernateQuery();
for(A nextA : resultSet) {
    for(B nextB : nextA.getBAssociations() {
        if(nextB instanceof C) {
            // do something for C
        } else if (nextB instanceof D) {
            // do something for D
        }
    }
}

Bコレクションが遅延ロードされており、BのすべてのインスタンスがHibernateプロキシであるため、このコードはCブロックまたはDブロックのいずれも実行できません。各インスタンスのプロキシを解除する方法が欲しいのですが。

注:クエリを最適化して、すべてのBを熱心にフェッチできることを理解しています。別の方法を探しています。

4

3 に答える 3

19

永続性ユーティリティに追加されたソリューションは次のとおりです。

public T unproxy(T proxied)
{
    T entity = proxied;
    if (entity instanceof HibernateProxy) {
        Hibernate.initialize(entity);
        entity = (T) ((HibernateProxy) entity)
                  .getHibernateLazyInitializer()
                  .getImplementation();
    }
    return entity;
}
于 2012-06-27T14:46:04.693 に答える
14

現在、Hibernateにはそのための専用メソッドがあります:org.hibernate.Hibernate#unproxy(java.lang.Object)

于 2019-03-07T13:27:59.100 に答える
2

HibernateProxyとgetImplementationMethodを使用したソリューションは正しいです。

ただし、コレクションがインターフェイスとして定義されており、Hibernateがインターフェイスにプロキシを提示しているため、これに遭遇していると思います。

これは、必要なことを行うためにインターフェースメソッドを使用する代わりに、なぜ「if」と「instanceof」を使用するのかという設計上の問題につながります。

したがって、ループは次のようになります。

for(B nextB : nextA.getBAssociations() {
    nextB.doSomething();
}

そうすれば、hibernateは「doSomething()」の呼び出しを実際の実装オブジェクトに委任することになり、違いがわかりません。

于 2012-06-27T19:08:57.663 に答える