Spring / Hibernate / JUnit - 没有绑定到线程的休眠会话
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/734614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring / Hibernate / JUnit - No Hibernate Session bound to Thread
提问by Marty Pitt
I'm trying to access the current hibernate session in a test case, and getting the following error:
我试图在测试用例中访问当前的休眠会话,并收到以下错误:
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)
org.hibernate.HibernateException:没有 Hibernate Session 绑定到线程,并且配置不允许在 org.springframework.orm.hibernate3.SpringSessionContext.currentSession(SpringSessionContext.java:63) 在 org.hibernate.impl 创建非事务性会话.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:574)
I've clearly missed some sort of setup, but not sure what.
我显然错过了某种设置,但不确定是什么。
Any help would be greatly appreciated. This is my first crack at Hibernate / Spring etc, and the learning curve is certainly steep!
任何帮助将不胜感激。这是我在 Hibernate / Spring 等方面的第一次尝试,学习曲线肯定很陡峭!
Code follows:
代码如下:
The offending class:
违规类:
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"));
}
}
Base class:
基类:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:applicationContext.xml"})
public class BaseDALTest extends AbstractJUnit4SpringContextTests {
public BaseDALTest()
{
super();
}
@Resource
protected SessionFactory sessionFactory;
}
applicationContext.xml:
应用上下文.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>
回答by Bogdan
Wrong, that will just fill your code with session management code.
错误,那只会用会话管理代码填充您的代码。
First, add a transaction management bean in your context:
首先,在您的上下文中添加一个事务管理 bean:
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
The second thing, extend AbstractTransactionalJUnit4SpringContextTests
第二件事,扩展 AbstractTransactionalJUnit4SpringContextTests
public class BaseDALTest
extends AbstractTransactionalJUnit4SpringContextTests{
Third thing, annotate you test class with
第三件事,用
@TransactionConfiguration
@Transactional
If your transaction demarcation is correct(surrounding your dao or service) you should be done.
如果您的交易划分是正确的(围绕您的 dao 或服务),您应该完成。
It's not nice to sprinkle session and transaction handling code all around your code (even inside your tests).
在你的代码周围(甚至在你的测试中)散布会话和事务处理代码是不好的。
回答by Nicolas
Please refer to the Spring documentation. There is a whole chapter on testing, and a section on transaction management:
请参阅 Spring 文档。有一整章是关于测试的,还有一节是关于事务管理的:
I've had success extending AbstractTransactionalJUnit4SpringContextTests, but there's a workaround:
我已经成功扩展了 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);
}
});
回答by Andreas Krueger
With the above Spring configuration, it should be sufficient to code
有了上面的Spring配置,写代码应该就够了
Session session = sessionFactory.getCurrentSession();
in your method and class to test. Session management is done by the Hibernate / Spring /JUnit test configuration, as later is done in the Hibernate / Spring configuration in the realapplication.
在您的方法和类中进行测试。会话管理是由 Hibernate/Spring/JUnit 测试配置完成的,后面在实际应用中的 Hibernate/Spring 配置中完成。
This is how it worked for my tests. In the final web application there will automatically be a Hibernate session associated with the current web request and therefore in testing there should be no sessionFactory.openSession()call.
这就是它对我的测试的工作方式。在最终的 Web 应用程序中,将自动有一个与当前 Web 请求相关联的 Hibernate 会话,因此在测试中应该没有sessionFactory.openSession()调用。
回答by Marty Pitt
Duh.
呃。
Session session =
sessionFactory.openSession();
会话会话 =
sessionFactory.openSession();
Session session = sessionFactory.getCurrentSession();
Oops.
哎呀。
(Edited since this was wrong, and getting upvoted).
(编辑,因为这是错误的,并得到了upvoted)。
回答by Jarek Przygódzki
Spring ignores hibernate.current_session_context_class=threadproperty (which you don't use) and wraps Hibernate's SessionFactoryin it's own transactional version as explained here
Spring 忽略hibernate.current_session_context_class=thread属性(您不使用它)并将 Hibernate 包装SessionFactory在它自己的事务版本中,如解释here
The solution to this is to set the property
解决这个问题的方法是设置属性
<property name="exposeTransactionAwareSessionFactory"><value>false</value></property>
in session factory bean configuration
在会话工厂 bean 配置中

