1

Spring 3.0.x での処理方法をより反映するように、古い Spring プロジェクトを作り直しています。

私が行った変更の 1 つは、リポジトリ/dao レイヤーに対するものでした。ベスト プラクティスでアドバイスされているように、私は からHibernateDaoSupportを使用するように拡張するのではなく、Spring 3.0.x 以降で動作するはずの をHibernateTemplate使用して HibernateSessionFactoryを直接使用します。sessionFactory.getCurrentSession()

これはプロジェクト全体にとって非常に大きな恩恵であり、HibernateTemplate. onStartUpただし、 @PostConstruct を使用していた (またはXML アプリケーションコンテキストでBean の属性を使用していた) Service メソッドを呼び出すことができなくなったことに気付きました。

たとえば、このメソッドは以前は を使用して問題なく動作してHibernateTemplateいましたが、現在、Hibernate はスレッドにバインドされたセッションがないことを訴える例外をスローします。

@Override
@PostConstruct
public void onStartUp() {
    logger.debug("Starting Bootstrap Service...");

    createSysAdminUser();
    createDefaultRoles();
    createDefaultThemes();

    createStopListIfDoesNotExist();
    stopListService.load();

    partialMappingService.load();
    dictionaryService.load();
}

このメソッド呼び出しを削除することもでき@PostConstructます... システムで唯一のものです。アプリケーションが新しいアプリケーションのデータをブートストラップするために起動するときに呼び出されます。ほとんどの場合、本番システムでは何もしませんが、新たに作成されたテストおよび開発用データベースに使用すると便利です。

なぜ、どのように修正できるかについてのアイデアはありますか?

ありがとう!

編集:これが私のトランザクション管理アドバイス構成です:

<aop:config>
    <aop:advisor advice-ref="transactionAdvice"
                 pointcut="execution(* *..service.*.*(..))" order="1"/>
    <!-- gets sub packages like service.user -->
    <aop:advisor advice-ref="transactionAdvice"
                 pointcut="execution(* *..service.*.*.*(..))" order="2"/>
</aop:config>

<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="find*" read-only="true" propagation="REQUIRED"/>
        <tx:method name="get*" read-only="true" propagation="REQUIRED"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
4

1 に答える 1

1

HibernateDaoSupport クラスのドキュメントで概説されているように、「このクラスは、SessionFactory が渡された場合、独自の HibernateTemplate インスタンスを作成します。その HibernateTemplate の 'allowCreate' フラグは、デフォルトで 'true' になります。」つまり、古いシステムでは、DAO は実際の制御下になくてもオンデマンドでセッションを開くことができました。

Spring が SessionFactory を管理している場合、SpringSessionContextを Hibernate のCurrentSessionContextとしてインストールします。を呼び出すSessionFactory.getCurrentSession()と、SpringSessionContext は Spring 管理の ThreadLocal で Session を探し、そこにない場合は失敗します。セッションは通常、次の 2 つの方法のいずれかで開かれ、そこに配置されます。open-session-in-view パターンを使用すると、新しいリクエストごとにそれが行われ、トランザクションの開始も行われます。あなたの場合、リクエストに応じてコードを実行していないため、OSIV は機能しておらず、明らかにアクティブなトランザクションでもありません。メソッドをトランザクション化すると、問題が解決されます。

于 2013-02-19T05:20:47.570 に答える