Spring/Hibernate/JUnit - сеанс Hibernate не связан с потоком
Я пытаюсь получить доступ к текущему сеансу спящего режима в тестовом примере и получить следующую ошибку:
org.hibernate.HibernateException: Нет Сессия Спящего режима связана с потоком и конфигурация не позволяет создавать не-транзакционной org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) в 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>
Ответы
Ответ 1
Неправильно, это просто заполнит ваш код кодом управления сеансом.
Сначала добавьте управление транзакциями bean в свой контекст:
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
Во-вторых, расширьте AbstractTransactionalJUnit4SpringContextTests
public class BaseDALTest
extends AbstractTransactionalJUnit4SpringContextTests{
В-третьих, аннотируйте тестовый класс с помощью
@TransactionConfiguration
@Transactional
Если ваша демаркация транзакций правильная (окружающая ваша дао или услуга), вы должны сделать.
Нехорошо посыпать сеанс и код обработки транзакций по всему вашему коду (даже внутри ваших тестов).
Ответ 2
Обратитесь к документации 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);
}
});
Ответ 3
С приведенной выше конфигурацией Spring должно быть достаточно кода
Session session = sessionFactory.getCurrentSession();
в вашем методе и классе для тестирования. Управление сеансом выполняется с помощью конфигурации Hibernate/ Spring/JUnit, как это было сделано позже в конфигурации Hibernate/Spring в реальном приложении.
Вот как это работает для моих тестов. В конечном веб-приложении автоматически будет сеанс Hibernate, связанный с текущим веб-запросом, и поэтому при тестировании не должно быть вызова sessionFactory.openSession()
.
Ответ 4
Duh.
Сеанс сеанса = sessionFactory.openSession();дел >
Session session = sessionFactory.getCurrentSession();
К сожалению.
(Отредактировано с тех пор, как это было неправильно, и получило преимущество).
Ответ 5
Spring игнорирует свойство hibernate.current_session_context_class=thread
(, которое вы не используете), и переносит Hibernates SessionFactory
в свою собственную транзакционную версию, как описано here
Решение этого - установить свойство
<property name="exposeTransactionAwareSessionFactory"><value>false</value></property>
в сеансе factory bean конфигурация