web-dev-qa-db-ja.com

Spring / Hibernate / JUnit-スレッドにバインドされたHibernateセッションがない

テストケースで現在の休止状態セッションにアクセスしようとすると、次のエラーが発生します。

org.hibernate.HibernateException:スレッドにバインドされたHibernateセッションがありません。構成では、org.hibernate.implのorg.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.Java:63)で非トランザクションセッションを作成できません。 .SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.Java:574)

私は明らかにいくつかの種類の設定を逃しましたが、何かはわかりません。

どんな助けでも大歓迎です。これはHibernate/Springなどでの最初の亀裂であり、学習曲線は確かに急勾配です。

コードは次のとおりです。

問題のあるクラス:

public class DbUnitUtil extends BaseDALTest {
    @Test
    public void exportDtd() throws Exception
    {

        Session session = sessionFactory.getCurrentSession();

        session.beginTransaction();
        Connection hsqldbConnection = session.connection(); 

        IDatabaseConnection connection = new DatabaseConnection(hsqldbConnection);

        // write DTD file
        FlatDtdDataSet.write(connection.createDataSet(), new FileOutputStream("test.dtd"));
    }
}

基本クラス:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:applicationContext.xml"})
public class BaseDALTest extends AbstractJUnit4SpringContextTests {
    public BaseDALTest()
    {
        super();
    }
        @Resource
        protected SessionFactory sessionFactory;
}

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName">
            <value>org.hsqldb.jdbcDriver</value>
        </property>
        <property name="url">
            <value>jdbc:hsqldb:mem:sample</value>
        </property>
        <property name="username">
            <value>sa</value>
        </property>
        <property name="password">
            <value></value>
        </property>
    </bean>

    <bean id="sessionFactory" class="com.foo.spring.AutoAnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="entityPackages">
            <list>
                <value>com.sample.model</value>
            </list>
        </property>
        <property name="schemaUpdate">
            <value>true</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect
                </prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>
</beans>
19
Marty Pitt

間違っています。これは、セッション管理コードでコードを埋めるだけです。

まず、コンテキストにトランザクション管理Beanを追加します。

    <bean id="transactionManager" 
          class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

2つ目は、AbstractTransactionalJUnit4SpringContextTestsを拡張することです。

    public class BaseDALTest 
           extends AbstractTransactionalJUnit4SpringContextTests{

3番目に、テストクラスに注釈を付けます

    @TransactionConfiguration
    @Transactional

トランザクションの境界が正しい場合(DAOまたはサービスを囲む)、完了します。

(テスト内であっても)コードの周りにセッションとトランザクション処理コードを散在させるのは良くありません。

31
Bogdan

Springのドキュメントを参照してください。テストに関する章全体とトランザクション管理に関するセクションがあります。

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/testing.html#testing-tx

AbstractTransactionalJUnit4SpringContextTestsを拡張することに成功しましたが、次善策があります。

TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    @Override
    protected void doInTransactionWithoutResult(TransactionStatus status) {
        // DAO has access to the session through sessionFactory.getCurrentSession()
        myDao.findSomething(id);
    }
});
5

上記のSpring構成では、コーディングするだけで十分です

_Session session = sessionFactory.getCurrentSession();
_

テストするメソッドとクラスで。セッション管理は、後でrealアプリケーションのHibernate/Spring構成で行われるように、Hibernate/Spring/JUnitテスト構成によって行われます。

これは私のテストでどのように機能したかです。最終的なWebアプリケーションでは、現在のWebリクエストに関連付けられたHibernateセッションが自動的に存在するため、テストではsessionFactory.openSession()呼び出しはありません。

2
Andreas Krueger

ええと。

セッションセッション= sessionFactory.openSession();

Session session = sessionFactory.getCurrentSession();

おっとっと。

(これは間違っていたため編集され、賛成投票されました)。

0
Marty Pitt

春はhibernate.current_session_context_class=threadプロパティ(使用しない)と説明されているように、HibernateのSessionFactoryを独自のトランザクションバージョンでラップします here

これに対する解決策は、プロパティを設定することです

<property name="exposeTransactionAwareSessionFactory"><value>false</value></property>

セッションファクトリBean構成

0