2017-01-09 25 views
2

我的Spring应用程序始终使用@org.springframework.transaction.annotation.Transactional来打开事务。为了减少与交易有关的不必要的开销,我已经开始删除不需要交易的应用领域中的一些注释。什么决定在@Transactional之外是否有休眠会话

这样做,我注意到@Controller类已删除@Transactional注释(在类级别或方法级别)仍然能够使用SessionFactory#getCurrentSession()。然而,当我从@Service(具体地说,的org.springframework.security.core.userdetails.UserDetailsService实现)取出@Transactional注释,并试图打电话SessionFactory#getCurrentSession(),我收到了以下:

Caused by: org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread 
    at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134) 
    at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014) 
    at com.xxx.datasource.AbstractDAO.getSession(AbstractDAO.java:35) 
    at com.xxx.datasource.UserDAO.getLoginUser(UserDAO.java:209) 
    at com.xxx.datasource.UserDAO.getLoginUser(UserDAO.java:199) 
    at com.xxx.spring.userdetails.service.UserDetailsServiceImpl.loadUserByUsername(UserDetailsServiceImpl.java:24) 
    at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:102) 
    ... 49 more 

这究竟是为什么/什么确定SessionFactory#getCurrentSession()将返回一个会话或抛出异常?

(春季4.1.9和4.3.11休眠)

+0

Spring通过使用过滤器保持打开供网站使用的hibernate会话。请参阅[http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.html]。但是这只适用于视图,而在服务器端,您需要拥有自己的事务注释标记来根据需要管理事务。 –

回答

1

方法调用SesssionFactory.getCurrentSession()的方法/类不@Transactional annotatated会导致异常作为TransactionSynchronizationManager.isSynchronizationActive()将返回false。它返回false,因为@Transaction方面尚未执行,因此事务同步对于当前线程保持不活动状态。如果它被执行,它将激活当前线程的事务同步。 方法看:TransactionSynchronizationManager.initSynchronizationTransactionSynchronizationManager.isSynchronizationActive

正如你提到你的@Controller类工作正常,这可能是因为他们要么不执行任何操作DAO或提前于控制器层正在交易的照顾。

+0

谢谢。我应该事先看过这个,但现在我可以确认'OpenSessionInViewInterceptor'是有罪的。我的印象是这种模式只有在请求到达视图层时才打开会话*;但事实上,由于它是一个弹簧拦截器,在控制器方法被击中之前,它在拦截器的'preHandle'阶段打开它。 – jlb