21

プロジェクトを Hibernate 3.0 から Hibernate 4.1.6 にアップグレードしています。(そして、現在Spring 3.1を使用しています)

sessionFactory.getCurrentSession()多くの記事と HibernateTemplate のドキュメントで、バージョン 4.0 以降の HibernateTemplate はサポートされておらず、その使用法をセッションを取得するための呼び出しに置き換える必要があることを読みました。

このプロジェクトは、使用が奨励されていた古いバージョンの Hibernate で開始されたため、現在、プロジェクト全体HibernateTemplateで 124 の使用法があります。HibernateTemplate残念ながら、これらすべての発生を に置き換えるとsessionFactory.getCurrentSession()、プロジェクトに回帰バグが挿入される可能性があります。HibernateTemplateさらに、 「現在の」セッションが存在しない非トランザクション コンテキストで使用された場所がいくつかあります。そのような場合はどうすればよいですか?新しいセッションを開き、それを自分で処理 (クローズ) しますか? 私が使っていた時はそうではありませんでしたHibernateTemplate

これらの問題に対処するための優れた戦略はありますか?

ありがとう。

関連する読書:

  1. 休止状態対。Spring - HibernateTemplate の履歴
  2. Hibernate Core 移行ガイド
  3. Spring 3.1 および Hibernate 4.1 への移行
  4. org.springframework.orm.hibernate3.HibernateTemplate
4

3 に答える 3

11

これが私が実際に行ったことです。これがこの問題の最善の解決策かどうかはわかりませんが、私たちの状況では、最もローカライズされた解決策を探していたので、それが最善のように思えました。

springframework.orm.hibernate3.HibernateTemplate を拡張し、新しい MyHibernateTemplate を作成しました。新しいテンプレートの主な役割は、ほとんどの hibernate3.HibernateTemplate が最終的に導く doExecute メソッドをオーバーライドし、古い SessionFactoryUtils (isSessionTransactional や applyTransactionTimeout など) によって提供された機能の一部を提供することです。

新しい doExecute は古いもののロジックを複製しますが、セッションを取得する SessionFactoryUtils.getNewSession の代わりに、最初に開いているセッション getSessionFactory().getCurrentSession() を探しようとします。

boolean newSessionOpened = false;
Session session;

if (enforceNewSession){
    session = SessionFactoryUtils.openSession(getSessionFactory());
    newSessionOpened = true;
} else {
    try {
        // look for an open session
        session = getSessionFactory().getCurrentSession();
    }
    catch (HibernateException ex) {
        try {
            // if there isn't an open session, open one yourself
            session = getSessionFactory().openSession();
            newSessionOpened = true;
        } catch (HibernateException e) {
            throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
        }
    }
}

// is the open session, is a session in a current transaction?
boolean existingTransaction = (!enforceNewSession &&
        (!isAllowCreate() || isSessionTransactional(session, getSessionFactory())));

このセッションを手動で閉じる必要があります。

    finally {
    // if session was used in an existing transaction restore old settings
    if (existingTransaction) {
        //logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
        disableFilters(session);
        if (previousFlushMode != null) {
            session.setFlushMode(previousFlushMode);
        }
    }
    // if not and a new session was opened close it
    else {
        // Never use deferred close for an explicitly new Session.
        if (newSessionOpened) {
            SessionFactoryUtils.closeSession(session);
            //_log.info("Closing opened Hibernate session");
        }
    }

私はこの答えを短くしようとしていますが、質問がある場合は、この問題についてさらに詳しく説明できます.

于 2012-10-02T17:44:36.170 に答える
2

ドキュメントのこのセクションを確認してください。それSessionFactory.getCurrentSession()はプラグイン可能であり、JTA トランザクションではなくThreadLocalSessionContext「現在のセッション」を保持する実装があります。ThreadLocalThreadLocalSessionContext は、そのセッションから作成されたハイバネート トランザクションの終了時にセッションも閉じるため、自分で閉じることを心配する必要はありませんSession

リグレッション バグの導入に関しては、ライブラリのアップグレードには常にリスクが伴います。特に、それが休止状態のようなアプリケーションのコアである場合はそうです。私ができる唯一のアドバイスは、アップグレードの前に、テスト スイートが十分にカバーされていることを確認することです。結局のところ、回帰バグをキャッチするのがテスト スイートの仕事です。

于 2012-08-28T19:42:32.977 に答える