6

私は本当に指を置くことができないいくつかの奇妙な動作をする Web アプリケーションを持っています。私の問題の核心は、残りのエンドポイントによって返される値に一貫性のない動作があることです。アプリケーションを起動すると、このエンドポイントを呼び出すたびにクエリが同じ値を返します。エンティティを更新すると、エンティティ マネージャーの動作がおかしくなり始めます。今、私のクエリは異なる結果を返し始めます。データベースにある値の代わりに古い値を返すか、結果リストにオブジェクトではなくプロキシが含まれている場合があります (混合)。 ここに画像の説明を入力

@transaction メソッドが正しく配置されていることを確認し、デバッグ スタックにトランザクション インターセプターが表示され、エンティティ マネージャーがバックエンドへの要求ごとに作成されます (したがって、guice 永続フィルターはありません)。

私の感覚では、問題はセッション コンテキストにあることを示しています。複数のリクエストで永続化コンテキストを再利用しているように感じます (しかし、実際には把握できません)。

これをすべて機能させるために、いくつかのフレームワークをまとめました。私は jax-rs 実装者として resteasy を使用しています。cdi 実装者として guice (4.0beta4) を、jpa 実装者として hibernate を実行します。entitymanager を注入するときにプロバイダーを使用する必要があるため (entitymanager はトランザクションごとに作成されるため)、これを EntityManagerProxy でラップしました。このクラスは EntityManager インターフェースを実装し、すべてのメソッドを provider.get().method() に委譲します。

public class EntityManagerProxy implements EntityManager {
    private final Provider<EntityManager> entityManagerProvider;

    @Inject
    public EntityManagerProxy(final Provider<EntityManager> entityManagerProvider) {
        this.entityManagerProvider = entityManagerProvider;
    }

    private EntityManager getEntityManager() {
        return entityManagerProvider.get();
    }

    @Override
    public void persist(final Object entity) {
        getEntityManager().persist(entity);
    }
}

私のguiceモジュールは次のようになります

public class OptiWEEEModule extends ServletModule implements Module {
    @Override
    protected void configureServlets() {

        super.configureServlets();
        bind(EntityManagerProxy.class);
        // JPA
        install(new JpaPersistModule("myPU"));
    }
}

これは漠然とした問題であることはわかっていますが、誰かが正しい方向に私を助けることができますか? これは、エラー メッセージを提供できる問題ではありません。

編集:問題を特定しました。プロファイラーを使用して、エンティティコンテキストが偽装によって再利用されていることを確認しました。これは、毎回クエリを実行するのではなく、@transactional アノテーションが渡されるたびに作成する必要がある既存のエンティティ マネージャーを使用することを意味します。

4

1 に答える 1

1

メーリングリストからこのアンサーを入手しました。

Guice perstist には、かなり変わった機能があり、いくつかの問題を引き起こします。私はあなたがちょうどそれを打っているかもしれないと思います

作業単位外のエンティティ マネージャーを要求すると、guice persist が暗黙的に作業単位を開始します。残念ながら、 UnitOfWork の isActive() はパッケージ プライベートです。また、作業単位がアクティブかどうかをテストすることはできません。

作業単位を明示的に開始および終了するには、2 つの方法があります。UnitOfWork とメソッド begin() および end() を使用できます。また、@Transactional アノテーションは作業単位を開始します。@Transactional は、作業単位が開始された場合にのみ、作業単位も終了します。

@Transactional メソッド内でのみエンティティ マネージャーを取得することをお勧めします。

@Transaction アノテーションは、春のものと同じ成熟度ではないとしか言​​えません。一方、プロバイダーを介して @Transactional マネージャー内でエンティティーマネージャーを取得しても、この問題は実際には解決されません。

もうすぐ生産に移行するので、残念ながら春に戻しましたが、締め切りを管理するための唯一の賢明な解決策でした.

于 2014-06-18T06:53:39.333 に答える