Spring 什么决定了在@Transactional之外是否可以使用hibernate会话

Spring 什么决定了在@Transactional之外是否可以使用hibernate会话,spring,hibernate,Spring,Hibernate,我的Spring应用程序始终使用@org.springframework.transaction.annotation.Transactional打开事务。为了减少与事务相关的不必要的开销,我已经开始删除应用程序中不需要事务的部分注释 在这样做时,我注意到删除了@Transactional注释(在类级别或方法级别)的@Controller类仍然能够使用SessionFactory\getCurrentSession()。但是,当我从@服务中删除@事务性注释(特别是org.springframew

我的Spring应用程序始终使用
@org.springframework.transaction.annotation.Transactional
打开事务。为了减少与事务相关的不必要的开销,我已经开始删除应用程序中不需要事务的部分注释

在这样做时,我注意到删除了
@Transactional
注释(在类级别或方法级别)的
@Controller
类仍然能够使用
SessionFactory\getCurrentSession()
。但是,当我从
@服务
中删除
@事务性
注释(特别是
org.springframework.security.core.userdetails.userdetails服务
)并试图调用
会话工厂#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)

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


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

Spring保持hibernate会话打开,以便web使用过滤器。请看[.但thuis仅用于视图,在服务器端,您需要有自己的事务注释标记,以便根据需要管理事务。谢谢。我应该事先查看一下,但现在我可以确认“OpenSessionInviewWinterCeptor”是罪魁祸首。我的印象是,此模式只是在打开会话一旦请求到达视图层;但实际上,由于它是一个spring拦截器,它会在拦截器的
预处理
阶段打开它,然后点击控制器方法。