web-dev-qa-db-ja.com

Hibernateセッションスレッドは安全ですか?

Hibernateのセッションがスレッドセーフかどうかを知る必要があります。ただし、実行のために新しいスレッドがすべてのスレッドにアタッチされていることは明らかです。しかし、私の質問は、あるスレッドでエンティティの値を更新したかどうかです。そのため、同じ時間の実行中に他のスレッドに反映されますか?

私の問題は、2つのスレッドから順次更新を実行すると、値が適切に更新されますが、更新をほぼすべて実行すると失敗します。

たとえば。テーブルの現在のステージ。

  ID      NAME      MARKS
------- --------- --------
  1       John       54

私は次のことをしようとしています:

Student student = session.load(Student.class, 1);
student.setMarks(student.getMarks() + 1);
session.update(student);
session.close();

上記のコードをループ10で実行しようとすると、テーブル "student"の "marks"の値が適切に更新されます。つまり、値は64に更新され、適切です。

しかし、スレッド環境で同じコードを実行しようとすると、悪い結果になります。

19
M.J.

実装者がスレッドセーフであることは意図されていません。代わりに、各スレッド/トランザクションは、SessionFactoryから独自のインスタンスを取得する必要があります。

これを念頭に置いても、トランザクションが機能するため、あなたの振る舞いは期待したものとは異なる場合があります。適切な トランザクション分離レベル を設定する必要があります。 設定ガイドhibernate.connection.isolationプロパティを参照してください。

21
Bozho

Hibernateセッションとスレッドが混在しない。

一度に複数のスレッドのセッションを使用しないでください。単一のスレッドのセッションのみを使用することをお勧めします。 DBセッションの実装は、adsafeである必要さえありません。

また、複数のスレッドで処理を開始したときにトランザクションがどうなるかを考慮する必要があります。トランザクションは現在のスレッドに関連付けられています。これはすぐに驚くべきこととなり、実装者が製品をテストしていない領域に入ります。

結局のところ、その沼で迷子になるには人生が短すぎます。

18
Peter Tillemans

Hibernateセッションはスレッドセーフではありません。 TheadLocalクラスを使用して、各スレッドのセッションを作成します。

 private static ThreadLocal<Session> threadSafeSession = new ThreadLocal<Session>() {
    protected Session initialValue(){
    return sf.openSession();
      }
    };

あなたのメソッドで、各スレッドのセッションを次のように取得してください:

Session session = threadSafeSession.get();
4
Goyal Vicky

セッションの作成方法によって異なります。

セッションは、休止状態で2つの方法で作成できます。

  1. getCurrentSession()

はい。セッションが存在しない場合、各スレッドのセッションを確実に作成するため、スレッドセーフを提供します。これにトランザクションと自動セッション終了がアタッチされています。

  1. openSession()

スレッドセーフではありません。開発者は手動でトランザクションとセッションのフラッシュとクローズ操作を管理する必要があります。

2
Sumanth Varada

Sessionオブジェクトは、単一のスレッドで使用するように設計されています。内部的には、セッションはスレッドセーフでない多くのデータ構造を使用するため、スレッドセーフにすることは不可能です。

さらに、スレッドセーフなSessionを使用する必要さえありません。ユースケースがキャッシュされたエンティティの共有である場合は、代わりにスレッドセーフであり、クラスター環境で使用できる2次レベルキャッシュを使用する必要があります。

とはいえ、スレッドセーフなセッションを使用する必要性は、データアクセス層の設計の欠陥を示すコードのにおいです。

0
Vicky