2009-04-09 4 views
19

Я пытаюсь получить доступ к текущей сессии спящего режима в тестовом случае, и получаю следующее сообщение об ошибке:Spring/Hibernate/JUnit - Нет Hibernate Session обязан Автор

org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here at org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) at org.hibernate.impl.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> 

ответ

31

Неправильно, это просто заполнит ваш код кодом управления сеансом.

Во-первых, добавить компонент управления транзакциями в вашем контексте:

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

Вторая вещь, продлить AbstractTransactionalJUnit4SpringContextTests

public class BaseDALTest 
      extends AbstractTransactionalJUnit4SpringContextTests{ 

Третья вещь, аннотировать протестировать класс с

@TransactionConfiguration 
    @Transactional 

Если ваша демаркация транзакций правильная (окружающая ваша dao o r), вы должны сделать это.

Неплохо посыпать сеанс и код обработки транзакций по всему вашему коду (даже внутри ваших тестов).

+0

В идеале вы должны иметь @Transactional (распространение = Propagation.REQUIRED), если вы тестируете некоторые тесты dao/repository, которые сами не аннотируются транзакциями, поскольку они зависят от класса, который инициировал быть в транзакции. В @TransactionConfiguration расскажите об этом менеджеру транзакций @TransactionConfiguration (transactionManager = "transactionManager", \t \t defaultRollback = true) – vsingh

+0

Я просто прочитал ваше сообщение, и мне удалось преодолеть эту проблему для меня. Теперь я не вижу новых строк в таблицах, хотя ошибка не возникает. Я предполагаю, что у меня есть способ остановить откат? – hephestos

0

Duh.

Session session = sessionFactory.openSession();

Session session = sessionFactory.getCurrentSession(); 

К сожалению.

(Отредактировано с тех пор, как это было неправильно, и получив преимущество).

+5

на самом деле, это совершенно неправильно. Вы хотите вызвать getCurrentSession(), иначе вы будете нести ответственность за его закрытие, и ваши транзакции не будут работать с моделью, зависящей от аннотации. – Justin

+0

@Justin - Спасибо, сообщение было обновлено на основе этой обратной связи. @ Downvoter - обратите внимание, почему? (Это сообщение обновлено более года!) –

2

При вышеуказанной конфигурации Spring, оно должно быть достаточно, чтобы закодировать

Session session = sessionFactory.getCurrentSession(); 

в методе и класс для тестирования. Управление сеансом выполняется с помощью тестовой конфигурации Hibernate/Spring/JUnit, как это делается позже в конфигурации Hibernate/Spring в действии реального.

Вот как это сработало для моих тестов. В последнем веб-приложении автоматически будет сеанс Hibernate, связанный с текущим веб-запросом, и поэтому при тестировании не должно быть вызова sessionFactory.openSession().

5

См. Документацию по весне.Существует целая глава о тестировании, а также раздел об управлении сделкой:

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

Я нашел зависимость от AbstractTransactionalJUnit4SpringContextTests довольно ограничительной, поэтому я действительно предлагаю ваше предложение TransactionTemplate - он работает! – teabot

0

Spring игнорирует hibernate.current_session_context_class=thread свойства (который вы не используете) и обертывает номер SessionFactory Hibernate в собственной транзакционной версии, как описано here

Решение это установить свойство

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

в конфигурации сеанса заводской боба

Смежные вопросы