问题描述
在尝试使用 @Service
注释类时,出现以下异常:
org.hibernate.HibernateException:无法获取当前线程的事务同步会话
在org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)〜[spring- orm-4.1.1.RELEASE.jar:4.1.1.RELEASE]
在org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)〜[hibernate-core-4.3.6.Final.jar :4.3.6.Final]
at webapp.base.repository.GenericDaoImpl.saveOrUpdate(GenericDaoImpl.java:59)〜[base-0.0.1-SNAPSHOT-classes.jar:na]
at com (PageViewDaoImpl.java:19)〜[site-0.0.1-SNAPSHOT.jar:na]
at com.example.repository.PageViewDaoImpl.saveOrUpdate(PageViewDaoImpl.java:14).example.repository.PageViewDaoImpl.saveOrUpdate(PageViewDaoImpl.java:19) 〜[site-0.0.1-SNAPSHOT.jar:na]
at com.example.service.PageViewServiceImpl.savePageView(PageViewServiceImpl.java:26)〜 [site-0.0.1-SNAPSHOT.jar:na]
at com.example.interceptor.PageViewInterceptor.preHandle(PageViewInterceptor.java:29)〜[site-0.0.1-SNAPSHOT.jar:na] $ b在org.springframework上$ b $ org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:130)〜[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
。 web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)〜[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
在org.springframework.web.servlet.DispatcherServlet.doService (DispatcherServlet.java:877)〜[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
在org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
在org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)[spring-webmvc-4.1.1 .RELEASE.jar:4.1.1.RELEASE]
在javax.servlet.http.HttpServlet.service(HttpServlet.java:620)[servlet-api-3.0.ja r:na]
在org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
在javax.servlet.http.HttpServlet.service(HttpServlet.java:727)[servlet-api-3.0.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303 )[tomcat-catalina-7.0.52.jar:7.0.52]
在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)[tomcat-catalina-7.0.52.jar:
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)[tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache .catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:488)[tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java :411)[tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationDispatc her.forward(ApplicationDispatcher.java:338)[tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:466)[tomcat -catalina-7.0.52.jar:7.0.52]
在org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:337)[tomcat-catalina-7.0.52.jar:7.0.52 ]
在org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:427)[tomcat-catalina-7.0.52.jar:7.0.52]
在org.apache.catalina。 core.StandardHostValve.invoke(StandardHostValve.java:200)[tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) [tomcat-catalina-7.0.52.jar:7.0.52]
在org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)[tomcat-catalina-7.0.52.jar:7.0 .52]
在org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)[tomcat-catalina-7.0.52.jar:7.0.52]
在org.apache。 catalina.conn ector.CoyoteAdapter.service(CoyoteAdapter.java:408)[tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) [tomcat-coyote-7.0.52.jar:7.0.52]
at org.apache.coyote.AbstractProtocol $ AbstractConnectionHandler.process(AbstractProtocol.java:607)[tomcat-coyote-7.0.52.jar:7.0 .52]
at org.apache.tomcat.util.net.JIoEndpoint $ SocketProcessor.run(JIoEndpoint.java:313)[tomcat-coyote-7.0.52.jar:7.0.52]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)[na:1.7.0_65]
在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:615)[na:1.7 .0_65]
at java.lang.Thread.run(Thread.java:745)[na:1.7.0_65]
我初始化应用程序的方式很复杂,所以我需要提供一个链接到完整的基本代码以获取更多信息:。
我使用这个作为maven覆盖。
以下是必要的代码:
初始化器(来自webapp-base):
public abstract class AbstractWebApplicationInitializer extends AbstractDispatcherServletInitializer {
@Override
protected String [] getServletMappings(){
return new String [] {/ *};
}
@Override
protected Filter [] getServletFilters(){
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding(UTF-8);
encodingFilter.setForceEncoding(true);
返回新的Filter [] {encodingFilter};
$ b @Override
protected WebApplicationContext createRootApplicationContext(){
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
ConfigurableEnvironment environment = rootContext.getEnvironment();
environment.setDefaultProfiles(production);
PropertyUtil propertyUtil = PropertyUtil.getInstance(environment.getActiveProfiles());
String [] basePackages = propertyUtil.getPropertySplitTrimmed(webapp,basePackages);
rootContext.scan(basePackages);
return rootContext; (
)
@Override
protected WebApplicationContext createServletApplicationContext(){
return new AnnotationConfigWebApplicationContext();
初始化程序(从我的webapp):
public class WebApplicationInitializer extends AbstractWebApplicationInitializer {
}
@Configuration
(来自webapp-base):
@Configuration
@EnableTransactionManagement
public class TransactionConfiguration {
@Bean
public DataSource dataSource()抛出IOException {
属性conProps = PropertyUtil.getInstance ().getProperties( JDBC);
if(conProps.containsKey(url)){
DriverManagerDataSource dataSource = new DriverManagerDataSource(conProps.getProperty(url),conProps);
dataSource.setDriverClassName(conProps.getProperty(driverClassName));
返回dataSource;
}
返回null;
}
@Bean
public SessionFactory sessionFactory()抛出IOException {
DataSource dataSource = dataSource();
if(dataSource!= null){
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.scanPackages(PropertyUtil.getInstance()。getPropertySplitTrimmed(hibernate,packagesToScan));
sessionBuilder.addProperties(PropertyUtil.getInstance()。getProperties(hibernate));
return sessionBuilder.buildSessionFactory();
}
返回null;
$ be $ b $ public HibernateTransactionManager transactionManager()抛出IOException {
SessionFactory sessionFactory = sessionFactory();
if(sessionFactory == null){
return null;
}
返回新的HibernateTransactionManager(sessionFactory);
$ / code $ / pre
$ b $ p $ @ c $ c $ @Configuration
$ public class MainConfiguration extends WebMvcConfigurerAdapter {
@Autowired
私人PageViewInterceptor pageViewInterceptor; //用@Component注解
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(pageViewInterceptor);
@Service
$ b $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ public class PageViewServiceImpl实现PageViewService {
@Autowired
私人PageViewDao pageViewDao;
@Override
public void savePageView(long ip,String visitPage,String userAgent){
PageView obj = new PageView();
obj.setVisitDate(new Date());
obj.setUserAgent(userAgent);
obj.setPage(visitPage);
obj.setIp(ip);
pageViewDao.saveOrUpdate(obj);
code $ <$ $ p
@Repository
$ b $ $ $
$ @ $ $ b $ public class PageViewDaoImpl extends GenericDaoImpl< PageView,Long>实现PageViewDao {
@Override
public void saveOrUpdate(PageView obj){
if(!obj.isBot()){
super.saveOrUpdate(obj);
}
}
}
公共抽象类GenericDaoImpl< T extends Identifier< I>,I extends Serializable>实现GenericDao< T,I> {
@Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory(){
if(sessionFactory == null){
throw new IllegalStateException(使用前没有在DAO中设置SessionFactory);
}
return sessionFactory;
}
@Transactional
public void saveOrUpdate(T obj){
getSessionFactory()。getCurrentSession()。saveOrUpdate(obj);
然后我自动装配 PageViewService
并使用它的方法。
我知道在这里有几个问题存在同样的问题,但我已经检查过任何东西:
-
提供@EnableTransactionManagement
- 服务将自动装配为接口
- 检查
@Transactional
无处不在使用getSessionFactory()。getCurrentSession()
- 没有有用的答案。我希望对所有组件进行组件扫描,而不仅仅是控制器
TransactionInterceptor
调用。 $ b
TransactionInterceptor $当你的web控制器调用实际的服务方法时,你的Spring服务代理会调用c $ c>。
-
确保您使用Spring hibernate4类:
org.springframework.orm.hibernate4.HibernateTransactionManager
-
Don不要覆盖
@Transactional
方法,而是使用模板模式。 尝试使用JPATransactionManager
,所以你可以用@PersistenceContext
注解注入当前的EntityManager
代替。这比在每个DAO方法中调用sessionFactory.getCurrentSession()
要优雅得多。
I'm getting the following exception when trying to use my @Service
annotated classes:
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134) ~[spring-orm-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014) ~[hibernate-core-4.3.6.Final.jar:4.3.6.Final]
at webapp.base.repository.GenericDaoImpl.saveOrUpdate(GenericDaoImpl.java:59) ~[base-0.0.1-SNAPSHOT-classes.jar:na]
at com.example.repository.PageViewDaoImpl.saveOrUpdate(PageViewDaoImpl.java:19) ~[site-0.0.1-SNAPSHOT.jar:na]
at com.example.repository.PageViewDaoImpl.saveOrUpdate(PageViewDaoImpl.java:14) ~[site-0.0.1-SNAPSHOT.jar:na]
at com.example.service.PageViewServiceImpl.savePageView(PageViewServiceImpl.java:26) ~[site-0.0.1-SNAPSHOT.jar:na]
at com.example.interceptor.PageViewInterceptor.preHandle(PageViewInterceptor.java:29) ~[site-0.0.1-SNAPSHOT.jar:na]
at org.springframework.web.servlet.HandlerExecutionChain.applyPreHandle(HandlerExecutionChain.java:130) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620) [servlet-api-3.0.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) [servlet-api-3.0.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:488) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:466) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:337) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardHostValve.throwable(StandardHostValve.java:427) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:200) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) [tomcat-catalina-7.0.52.jar:7.0.52]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040) [tomcat-coyote-7.0.52.jar:7.0.52]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607) [tomcat-coyote-7.0.52.jar:7.0.52]
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:313) [tomcat-coyote-7.0.52.jar:7.0.52]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_65]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_65]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_65]
The way I initialize my application is complicated so I need to provide a link to the full base code to get additional information: https://github.com/dtrunk90/webapp-base.I'm using this as a maven overlay.
And here is the necessary code:
Initializer (from webapp-base):
public abstract class AbstractWebApplicationInitializer extends AbstractDispatcherServletInitializer {
@Override
protected String[] getServletMappings() {
return new String[] {"/*"};
}
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceEncoding(true);
return new Filter[] {encodingFilter};
}
@Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
ConfigurableEnvironment environment = rootContext.getEnvironment();
environment.setDefaultProfiles("production");
PropertyUtil propertyUtil = PropertyUtil.getInstance(environment.getActiveProfiles());
String[] basePackages = propertyUtil.getPropertySplitTrimmed("webapp", "basePackages");
rootContext.scan(basePackages);
return rootContext;
}
@Override
protected WebApplicationContext createServletApplicationContext() {
return new AnnotationConfigWebApplicationContext();
}
}
Initializer (from my webapp):
public class WebApplicationInitializer extends AbstractWebApplicationInitializer {
}
@Configuration
(from webapp-base):
@Configuration
@EnableTransactionManagement
public class TransactionConfiguration {
@Bean
public DataSource dataSource() throws IOException {
Properties conProps = PropertyUtil.getInstance().getProperties("jdbc");
if (conProps.containsKey("url")) {
DriverManagerDataSource dataSource = new DriverManagerDataSource(conProps.getProperty("url"), conProps);
dataSource.setDriverClassName(conProps.getProperty("driverClassName"));
return dataSource;
}
return null;
}
@Bean
public SessionFactory sessionFactory() throws IOException {
DataSource dataSource = dataSource();
if (dataSource != null) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(dataSource);
sessionBuilder.scanPackages(PropertyUtil.getInstance().getPropertySplitTrimmed("hibernate", "packagesToScan"));
sessionBuilder.addProperties(PropertyUtil.getInstance().getProperties("hibernate"));
return sessionBuilder.buildSessionFactory();
}
return null;
}
@Bean
public HibernateTransactionManager transactionManager() throws IOException {
SessionFactory sessionFactory = sessionFactory();
if (sessionFactory == null) {
return null;
}
return new HibernateTransactionManager(sessionFactory);
}
}
@Configuration
(from my webapp):
@Configuration
public class MainConfiguration extends WebMvcConfigurerAdapter {
@Autowired
private PageViewInterceptor pageViewInterceptor; // Is annotated with @Component
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(pageViewInterceptor);
}
}
@Service
:
@Service
public class PageViewServiceImpl implements PageViewService {
@Autowired
private PageViewDao pageViewDao;
@Override
public void savePageView(long ip, String visitPage, String userAgent) {
PageView obj = new PageView();
obj.setVisitDate(new Date());
obj.setUserAgent(userAgent);
obj.setPage(visitPage);
obj.setIp(ip);
pageViewDao.saveOrUpdate(obj);
}
}
@Repository
:
@Repository
public class PageViewDaoImpl extends GenericDaoImpl<PageView, Long> implements PageViewDao {
@Override
public void saveOrUpdate(PageView obj) {
if (!obj.isBot()) {
super.saveOrUpdate(obj);
}
}
}
public abstract class GenericDaoImpl<T extends Identifier<I>, I extends Serializable> implements GenericDao<T, I> {
@Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
if (sessionFactory == null) {
throw new IllegalStateException("SessionFactory has not been set on DAO before usage");
}
return sessionFactory;
}
@Transactional
public void saveOrUpdate(T obj) {
getSessionFactory().getCurrentSession().saveOrUpdate(obj);
}
}
Then I'm autowiring PageViewService
and use its methods.
I know there are several questions with the same problem here but I already checked anything:
Could not obtain transaction-synchronized Session for current thread
@EnableTransactionManagement
is provided- Services wil be autowired as interfaces
HibernateException: Could not obtain transaction-synchronized Session for current thread
- Checked for
@Transactional
everywhere I usegetSessionFactory().getCurrentSession()
Spring Hibernate - Could not obtain transaction-synchronized Session for current thread
@EnableTransactionManagement
is provided- Checked for
@Transactional
everywhere I usegetSessionFactory().getCurrentSession()
- There's no helpful answer. I want component scanning for all my components, not only controller
Looking at your log I can instantly tell that your transaction settings are wrongly set. That's because there's no TransactionInterceptor
call in your stack trace.
The TransactionInterceptor
is called by your Spring Service proxies when your web controllers call the actual Service methods.
Make sure you use the Spring hibernate4 classes:
org.springframework.orm.hibernate4.HibernateTransactionManager
Don't override
@Transactional
methods, but use a template patterns instead.Try using
JPATransactionManager
instead so you can inject the currentEntityManager
with the@PersistenceContext
annotation instead. This is much more elegant than callingsessionFactory.getCurrentSession()
in every DAO method.
这篇关于HibernateException:无法获取当前线程的事务同步会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!