2

永続化のためにhibernate/JPAを使用するアプリケーションがあります。Springを使用しています。永続化された Bean の一部は、 REST サービスから取得した外部オブジェクト
に依存しています。

この REST サービスのクライアント スタブは、登録済みの Spring サービスです。

休止状態のロードの過程で、これらの外部オブジェクトのロードをラップしたいと思います。このようにして、複雑な HQL クエリを介してオブジェクトを取得した場合でも、オブジェクトがロード後に常に有効であることが確実にわかります。

問題は、どの方法を使用しても、永続化された Bean でSpring アプリケーション コンテキスト(したがって REST クライアント) を取得するのに苦労することです。

私は次のことを試しました:

  • UserTypeを使用して、ID を介して REST からオブジェクトをフェッチします
    。CustomUserType は Hibernate によってインスタンス化されるため、Spring インジェクションは発生しません。
  • @AfterLoad JPA アノテーションを使用します。
    これはさらに悪いことです。EntityManager、Session、または Spring コンテキストは利用できません
  • User LifeCycleインターフェイス、onLoad(Session s, Serializable id) メソッド:
    ここでセッションにアクセスできます。しかし、 ApplicationContextに対応するカスタム セッションを作成する方法がわかりません。

当分の間、私は汚い回避策を使用しています: Spring ワールド外のオブジェクトがそれにアクセスできるように、静的ゲッターを提供するApplicationHolder Spring サービス。

休止状態または永続化された Bean のコンテキストを認識させる方法について、最善の方法はありますか?

THks

編集

私のDAOでそれを行うのが私の最初のアプローチでしたが、実際には次のようにフェッチが必要なサブオブジェクトがたくさんあります:

LocalObject
* - localSubObject1
    - refToExternalObject ----------> externalObject1
* - localSubObject2 
    - refToExternalObject ----------> externalObject2
    - refToExternalObject ----------> externalObject3

LocalObject に一貫性のあるクリーンなロードを持たせたいと考えています。

このようにして、DAO に Complex HQL を記述できるようになり、外部オブジェクトのフェッチを気にする必要がなくなりました。

4

2 に答える 2

1

私のコメントを説明するための解決策の簡単なスケッチ:

@Component
public class HibernateDao {

    @Resource
    private SessionFactory sessionFactory;
    @Resource
    private RestClient restClient;


    public LocalObject loadLocalObject(Serializable id) {
        LocalObject localObject = sessionFactory.getCurrentSession().load(id);
        ExternalObject externalObject = restClient.getExternalObject(id);

        localObject.setVal(externalObject.getVal())
        // ... more of this ...

        return localObject;
    }
}
于 2013-01-04T16:24:27.070 に答える
1

Dao で実行したくない場合は、次の方法でうまくいく可能性があります。

@Component
public class MyPostLoadEventListener implements PostLoadEventListener {

    @Resource
    private SessionFactoryImpl sessionFactoryImpl;
    @Resource
    private RestClient restClient;

    @PostConstruct
    public void installAsEventListener() {
        sessionFactoryImpl.getServiceRegistry()
                              .getService(EventListenerRegistry.class)
                              .getEventListenerGroup(EventType.POST_LOAD)
                              .appendListener(this);
    }

    @Override
    public void onPostLoad(PostLoadEvent event) {
        if (event.getEntity() instanceof LocalObject) {
            // fill with data from RestClient
        }
    }
}

これは少し厄介ですが、残念ながら、Hibernate EventListeners を登録する別の方法 (設定またはIntegratorsを介して) は、直接インスタンス化されるため、Spring Bean では使用できません (この放棄された JIRA エントリで述べたように)。

それが役立つことを願っています。

于 2013-01-04T17:19:30.790 に答える