19 votes

Spring / Hibernate / JUnit - Pas de session Hibernate liée à un thread

J'essaie d'accéder à la session hibernate en cours dans un scénario de test, et j'obtiens l'erreur suivante :

org.hibernate.HibernateException : Non Session Hibernate liée à un thread et configuration ne permet pas la création d'une session non-transactionnelle ici à org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) à l'adresse org.hibernate.impl.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)

J'ai manifestement manqué une sorte d'installation, mais je ne sais pas laquelle.

Toute aide serait grandement appréciée. C'est mon premier essai avec Hibernate / Spring, etc., et la courbe d'apprentissage est certainement raide !

Le code est le suivant :

La classe incriminée :

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"));
    }
}

Classe de base :

@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>

31voto

Bogdan Points 2116

Faux, cela va juste remplir votre code avec du code de gestion de session.

Tout d'abord, ajoutez un haricot de gestion des transactions dans votre contexte :

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

La deuxième chose, étendre AbstractTransactionalJUnit4SpringContextTests

    public class BaseDALTest 
           extends AbstractTransactionalJUnit4SpringContextTests{

Troisièmement, annotez votre classe de test avec

    @TransactionConfiguration
    @Transactional

Si la démarcation de votre transaction est correcte (autour de votre dao ou service), vous devriez avoir terminé.

Il n'est pas agréable de saupoudrer du code de gestion des sessions et des transactions tout autour de votre code (même dans vos tests).

5voto

Veuillez vous référer à la documentation de Spring. Il y a un chapitre entier sur les tests, et une section sur la gestion des transactions :

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

J'ai réussi à étendre AbstractTransactionalJUnit4SpringContextTests, mais il y a une solution de rechange :

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);
    }
});

2voto

Andreas Krueger Points 851

Avec la configuration Spring ci-dessus, il devrait être suffisant de coder

Session session = sessionFactory.getCurrentSession();

dans votre méthode et votre classe à tester. La gestion des sessions est effectuée par la configuration de test Hibernate / Spring /JUnit, comme plus tard dans la configuration Hibernate / Spring dans le fichier réel application.

C'est ainsi que cela a fonctionné pour mes tests. Dans l'application web finale, il y aura automatiquement une session Hibernate associée à la requête web en cours et donc, dans les tests, il ne devrait pas y avoir d'erreur. sessionFactory.openSession() appeler.

0voto

Marty Pitt Points 8239

Duh.

Session session = sessionFactory.openSession() ;

Session session = sessionFactory.getCurrentSession();

Oups.

(Modifié puisque c'était faux et qu'il y a eu des votes positifs).

0voto

Jarek Przygódzki Points 1215

Le printemps ignore hibernate.current_session_context_class=thread propriété ( que vous n'utilisez pas ) et englobe l'outil d'Hibernate SessionFactory dans sa propre version transactionnelle comme expliqué aquí

La solution à ce problème est de définir la propriété

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

dans la configuration de la fabrique de session

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X