web-dev-qa-db-ja.com

休止状態のセッションを制御する(手動で閉じる場合)

私は休止状態のAPIとチュートリアルを読んだ後、休止状態に慣れていないので、使用しない場合はセッションを閉じる必要があるようです。

このような:

Session sess=getSession();
Transcration tx=sess.beginTranscration();
//do something using teh session
sess.save(obj);
tx.commit();
sess.close;

スタンドアロンアプリケーションで使用する場合、疑問はありません。ただし、Webアプリで使用するかどうかはわかりません。

例えば、私はサーブレットを持っています:TestServletはクライアントからパラメーターを受け取り、次のようにパラメーターに従って何かを照会するためにManagerを呼び出します:

class TestServlet{
  doGet(HttpServletRequset,httpServletResponse){
    String para1=request.getParam...();
    String para2=.....
    new Manager().query(para1,para2);
  }
}

class Manager{
  public String query(String pa1,String pa2){
    Session=....// get the session
    //do query using para1 and 1
    session.close() //Here, I wonder if I should close it.
  }
}

クエリメソッドでセッションを閉じる必要がありますか?

誰かが休止状態でのセッションはjdbcでの接続のようだと言ったので。頻繁に開いたり閉じたりするのが正しい方法ですか?

ところで、tx.commit()は毎回必要ですか?

また、セッションがapiでスレッドセーフではないことがわかったので、サーブレットでセッションを使用することに関するスレッドの問題は何ですか。

63
hguser

私は休止状態のAPIとチュートリアルを読んだ後、休止状態に慣れていないので、使用しない場合はセッションを閉じる必要があるようです。

終了したら閉じる必要があります(ただし、これは後で説明するように自動的に実行できます)。

スタンドアロンアプリケーションで使用する場合、疑問はありません。ただし、Webアプリで使用する場合はわかりません。

さて、セクションの 11.1.1。作業単位 のドキュメントで説明されているように、themost commonマルチユーザークライアント/サーバーアプリケーションのパターンは、session-per-requestです。

たとえば、クライアントからパラメーターを受け取るservlet:TestServletがある場合、マネージャーを呼び出してパラメーターに従って何かを照会します。このように(...)queryメソッドでセッションを閉じる必要がありますか?

それはすべて、セッションの取得方法に依存します。

  • sessionFactory.getCurrentSession()を使用すると、トランザクションのライフサイクルにバインドされた「現在のセッション」を取得し、トランザクションが終了(コミットまたはロールバック)したときに自動的にフラッシュされて閉じられます。
  • sessionFactory.openSession()を使用することにした場合は、セッションを自分で管理し、「手動で」フラッシュして閉じなければなりません。

session-per-requestパターンを実装するには、最初のアプローチを優先します(はるかに簡単で冗長ではありません)。 long conversations を実装するには、2番目のアプローチを使用します。

Wikiページ セッションとトランザクション は、このトピックに関するドキュメントを補足するものです。

ところで、tx.commit()は毎回必要ですか?

非トランザクションデータアクセスと自動コミットモード を読みたい場合がありますが、簡単に言えば、トランザクション内でHibernateコードを実行する必要があります。明示的なトランザクション境界(つまり、明示的なbeginTransactionおよびcommit)を使用します。

また、セッションがapiでスレッドセーフではないことがわかったので、サーブレットでセッションを使用することに関するスレッドの問題は何ですか。

サーブレットのインスタンス変数にしないでください。問題はありません。

参照資料

114
Pascal Thivent

セッションは、getCurrentSession()が初めて呼び出されるたびに開かれ、トランザクションが終了すると閉じられます。

これにより、セッションが存在しない場合は新しいセッションが作成され、既に存在する場合は既存のセッションが使用されます。これは、自動フラッシュ属性と自動クローズ属性の両方でtrueとして自動的に構成され、Sessionが自動的にフラッシュされて閉じられることを意味します。

getCurrentSession()を使用している場合、接続を閉じる必要はありません。これを試そうとすると、例外が発生します。

0
Virendra khade

sessionFactory.openSession()を介してセッションを取得する場合は、外部で閉じるにする必要があります。意図しない期間にセッションを開くと、データリークが発生する可能性があります。さらに、Webアプリのセキュリティの脅威に招待することもできます。

0
user6069813

ThreadLocalを使用できます。

_public class MyUtil {
private static SessionFactory sessionFactory;
private static ServiceRegistry serviceRegistry;
private static final ThreadLocal<Session> threadLocal;

static {
try {
    Configuration configuration = new Configuration();
    configuration.configure();
    serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
    sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    threadLocal = new ThreadLocal<Session>();

    } catch(Throwable t){
      t.printStackTrace();
      throw new ExceptionInInitializerError(t);
    }
}
public static Session getSession() {
    Session session = threadLocal.get();
    if(session == null){
        session = sessionFactory.openSession();
        threadLocal.set(session);
    }
    return session;
}

public static void closeSession() {
    Session session = threadLocal.get();
    if(session != null){
    session.close();
    threadLocal.set(null);
    }
}

public static void closeSessionFactory() {
    sessionFactory.close();
    StandardServiceRegistryBuilder.destroy(serviceRegistry);
   }
}
_

ここでは、SessionFactoryは静的ブロックを使用して1回だけ初期化されます。したがって、mainクラスがgetSession()を呼び出すたびに、threadLocalオブジェクトでSessionオブジェクトの存在が最初にチェックされます。したがって、このプログラムはスレッドセーフを提供します。各操作の後、closeSession()はセッションを閉じ、threadLocalオブジェクトをnullに設定します。最後にcloseSessionFactory()を呼び出します。

0
AnirbanDebnath