HibernateException:无法获取当前线程的事务同步会话

尝试使用我的@Service注释类时,我收到以下exception:

 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] 

我初始化应用程序的方式很复杂,所以我需要提供完整基本代码的链接以获取更多信息: https : //github.com/dtrunk90/webapp-base 。 我正在使用它作为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); 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(); } } 

初始化程序(来自我的webapp):

 public class WebApplicationInitializer extends AbstractWebApplicationInitializer { } 

@Configuration (来自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 (来自我的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 implements PageViewDao { @Override public void saveOrUpdate(PageView obj) { if (!obj.isBot()) { super.saveOrUpdate(obj); } } } public abstract class GenericDaoImpl<T extends Identifier, I extends Serializable> implements GenericDao { @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); } } 

然后我自动assemblyPageViewService并使用它的方法。

我知道这里有几个问题有同样的问题,但我已经检查了一切:

无法获取当前线程的事务同步会话

  • 提供了@EnableTransactionManagement
  • 服务将作为接口自动assembly

HibernateException:无法获取当前线程的事务同步会话

  • 检查@Transactional到处都是我使用getSessionFactory().getCurrentSession()

Spring Hibernate – 无法为当前线程获取事务同步的Session

  • 提供了@EnableTransactionManagement
  • 检查@Transactional到处都是我使用getSessionFactory().getCurrentSession()

org.hibernate.HibernateException:无法获取当前线程的事务同步会话

  • 没有有用的答案。 我想要对所有组件进行组件扫描,而不仅仅是控制器

查看您的日志,我可以立即判断您的交易设置是否设置错误。 那是因为堆栈跟踪中没有TransactionInterceptor调用。

当Web控制器调用实际的Service方法时, TransactionInterceptor会调用TransactionInterceptor

  1. 确保使用Spring hibernate4类:

     org.springframework.orm.hibernate4.HibernateTransactionManager 
  2. 不要覆盖@Transactional方法,而是使用模板模式。

  3. 请尝试使用JPATransactionManager以便您可以使用@PersistenceContext注释注入当前的EntityManager 。 这比在每个DAO方法中调用sessionFactory.getCurrentSession()要优雅得多。

您必须对@Service@Repository使用@Transactional 。 它允许Spring通过Transaction支持应用和创建代理。

在您的代码中, @Service类在类级别或方法级别中没有@Transacional

第二

实现WebApplicationInitializer的类在哪里? 我看到你正在扩展课程..无论如何,我的观点是,以下是类似的地方:

 @Override public void onStartup(ServletContext container) { // Create the 'root' Spring application context AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.register(CentralServerConfigurationEntryPoint.class); // Manage the lifecycle of the root application context container.addListener(new ContextLoaderListener(rootContext)); // Create the dispatcher servlet's Spring application context AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext(); dispatcherServlet.register(CentralWebConfigurationEntryPoint.class); // Register and map the dispatcher servlet ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } 

其中CentralServerConfigurationEntryPoint.class必须只扫描必须在服务器端工作的组件( @Service @Repository@Service @Repository@Repository @Configuration for Transaction,Hibernate,DataSource等)

其中CentralWebConfigurationEntryPoint必须只扫描必须在客户端/ Web端工作的组件( @Controller@Configuration for Formatters,Tiles,Converters等)

我不明白你的代码

 @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(); } 

我的观点是:您必须有两个AnnotationConfigWebApplicationContext用于服务器和Web端。

这个问题的答案非常简短,你只需要在你的dao类中使用@Transactional,将你的配置类标记为@EnableTransactionManagement并创建一个bean

 **@Bean public PlatformTransactionManager transactionManager() { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource()); return transactionManager; }** 

在这里,如果您看到EnableTransactionManagement批注中提供的代码示例,则建议使用DataSourceTransactionManager而不是HibernateTransactionManager。