是什么决定了@Transactional之外的休眠会话是否可用

时间:2017-01-09 01:31:41

标签: spring hibernate

我的Spring应用程序始终使用@org.springframework.transaction.annotation.Transactional来打开交易。为了减少与交易相关的不必要的开销,我已经开始在应用程序中不需要交易的区域中删除其中一些注释。

在这样做的过程中,我注意到已删除@Controller注释的@Transactional类(在类级别或方法级别)仍然能够使用SessionFactory#getCurrentSession()。但是,当我从@Transactional删除@Service注释(具体来说,是org.springframework.security.core.userdetails.UserDetailsService的实现)并尝试调用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()是返回会话还是抛出异常?

(Spring 4.1.9和Hibernate 4.3.11)

1 个答案:

答案 0 :(得分:1)

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

正如你所提到的,你的@Controller类工作正常,可能是因为他们没有执行任何dao操作,或者控制器上的前面层正在处理事务。