1

Spring / Hibernateアプリケーションでセッションファクトリ(DAOオブジェクトに挿入されたシングルトンBean)を使用していて、サービスレイヤーアーキテクチャを使用していますが、次の問題があります。

データベースからドメインオブジェクトを取得するときはいつでも、休止状態のセッションファクトリによって提供される新しいセッションを使用します。同じ行を複数回リクエストする場合、同じドメインオブジェクトのインスタンスが複数存在することになります。(単一のセッションを使用する場合、同じ参照を指す複数のオブジェクトが返されます)したがって、これらのドメインオブジェクトのいずれかに加えられた変更は、この同じ行を表す他のドメインオブジェクトによって考慮されません。

複数のビューを持つSWINGアプリケーションを開発していて、異なる場所(およびクエリ)から同じDB行を取得しているため、同じインスタンスを指すドメインオブジェクトを取得する必要があります。

私の質問は、SessionFactoryを使用してこれを実現する方法ですか?そうでない場合は、アプリケーション全体で単一のセッションを使用することをお勧めしますか?その場合、このセッションをどこでどのように宣言すればよいですか?(sessionFactoryのようにDAOオブジェクトに注入されるBeanである必要がありますか?)

よろしくお願いします

4

2 に答える 2

0

SpringのHibernateセッション(私はこれをh-sessionと呼びます)は通常スレッドにバインドされているため(HibernateTransactionManagerについてはJavaDocを参照)、h-sessionはスレッドごとに1回取得されます。

1つのhセッションで「get」または「load」を複数回呼び出す場合に同じオブジェクトを取得するために使用される第1レベルのキャッシュ(h-sessionキャッシュ-常にオン)。ただし、このキャッシュはクエリでは機能しません。

また、トランザクション分離に関連する問題を忘れてはなりません。ほとんどのアプリケーションでは、「読み取りコミット」分離レベルが使用されます。そして、この分離レベルは、「繰り返し不可能な読み取り」として知られる現象の影響を受けます。基本的に、この行を複数回クエリすると、1つのトランザクションで同じ行の複数のバージョンを受け取ることができます(別のトランザクションのクエリ間で行が更新される可能性があるため)。

したがって、1回のhセッション/トランザクションで同じデータを複数回クエリしないでください。

于 2012-05-05T19:14:07.187 に答える
0

Open Session in View Patternを探しています。基本的に、アプリケーションの起動時に Session をスレッドにバインドし、アプリケーションの存続期間を通じて同じ Session を使用する必要があります。セッションを次のように保持するシングルトン util クラスを作成することで、これを行うことができます (例では のEntityManager代わりにを使用してSessionいますが、コードは本質的に同じになります)。

  private static EntityManager        entityManager;

  public static synchronized void setupEntityManager() {
    if (entityManager == null) { 
      entityManager = entityManagerFactory.createEntityManager();
    } 

    if (!TransactionSynchronizationManager.hasResource(entityManagerFactory)) {
      TransactionSynchronizationManager.bindResource(entityManagerFactory, new EntityManagerHolder(entityManager));
    }
  }

  public static synchronized void tearDownEntityManager() {
    if (entityManager != null) { 
      if (entityManager.isOpen()) { 
        entityManager.close();
      } 

      if (TransactionSynchronizationManager.hasResource(entityManagerFactory)) { 
        TransactionSynchronizationManager.unbindResource(entityManagerFactory);
      } 

      if (entityManagerFactory.isOpen()) { 
        entityManagerFactory.close();
      } 
    } 
  }

Open Session in View パターンに関連する固有のリスクがあることに注意してください。たとえば、アプリケーションでスレッドを使用するつもりであるというコメントに気付きました。セッションはスレッドセーフではありません。そのため、スレッド化された方法でデータベースにアクセスしようとしていないことを確認する必要があります.*

また、コレクションの取得戦略にも注意する必要があります。開いているセッションと遅延読み込みでは、データベースに過度の負荷をかける可能性が常にあります。

*以前、NetBeans アプリケーションでこのアプローチを使用したことがありますが、これは特定のタスクにスレッドを使用することを知っています。問題はありませんでしたが、多くのリスクがあることに注意する必要があります。

編集

状況によっては、ドメイン オブジェクトをセッションから削除し、切り離されたオブジェクトを後で使用できるようにキャッシュすることもできます。この戦略では、ドメイン オブジェクトが頻繁に更新されないようにする必要があります。更新しないと、アプリケーションが不必要に複雑になります。

于 2012-05-05T20:11:44.397 に答える