在Spring Transaction JUnit测试中自动assemblyHibernate会话的正确方法
这个问题类似于前一个问题 。 我试图在我的一个Spring-JUnit-Transactional测试中@Autowire
一个Hibernate Session但是我得到了这个exception:
java.lang.IllegalStateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional ...
这是我的JUnit类:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"/applicationContext.xml"}) @TransactionConfiguration(transactionManager="transactionManager") @Transactional public class MyTest { @Qualifier("session") @Autowired private Session session; @Test public void testSomething() { session.get(User.class, "me@here.com"); } }
如果我@Autowire
一个SessionFactory
并以编程方式获取我的Session
(而不是在Spring XML中定义它),那么每个都可以正常工作:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"/applicationContext.xml"}) @TransactionConfiguration(transactionManager="transactionManager") @Transactional public class MyTest{ @Qualifier("sessionFactory") @Autowired private SessionFactory sessionFactory; @Test public void testSomething() { Session session = SessionFactoryUtils.getSession(sessionFactory, false); session.get(User.class, "me@here.com"); } }
但是,如果我使用在我的Spring XML中定义我的
Session
,那么我可以得到我的原始示例:
... classpath:/hibernate.cfg.xml org.hibernate.cfg.AnnotationConfiguration
我的问题是:为什么需要在我的unit testing中只有一个线程有限的事务上下文? 定义
Hibernate Session
bean的正确方法是什么?
SessionFactoryUtils.getSession()与获取Session的任何其他方式一样好。 HibernateDaoSupport.getSession()会做同样的事情。
你需要scoped-proxy的原因是因为时间问题。 如果没有scoped-proxy,它似乎是在测试开始之前注入Session,因此在事务开始之前注入会话,因此你会得到错误。
通过添加scoped-proxy,它代理Session并注入它,因此它不会预先注入实际会话(在事务开始之前),而是仅在测试运行时获取并调用它,当它实际需要创建一个时打电话给它。
我认为“正确”的方式是注入SessionFactory
,并以编程方式从中获取Session。 您获得exception的原因归结为SessionFactoryUtils.getSession()
的记录行为:
获取给定SessionFactory的Hibernate会话。 知道并将返回绑定到当前线程的任何现有对应Session,例如在使用HibernateTransactionManager时。 否则,如果“allowCreate”为true,则会创建一个新的Session。
由于没有任何内容将会话绑定到当前事务,因此失败。
我的建议是使用HibernateTemplate
– 在你的上下文中定义一个,并将其自动装入你的测试中。 HibernateTemplate
与war会话具有大部分相同的操作,但会为您处理会话处理。 你应该能够做到:
hibernateTemplate.get(User.class, "me@here.com");