本文介绍了HibernateException:无法获取当前线程的事务同步会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试使用 @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


  1. 确保您使用Spring hibernate4类:

      org.springframework.orm.hibernate4.HibernateTransactionManager 


  2. 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 use getSessionFactory().getCurrentSession()

Spring Hibernate - Could not obtain transaction-synchronized Session for current thread

  • @EnableTransactionManagement is provided
  • Checked for @Transactional everywhere I use getSessionFactory().getCurrentSession()

org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread

  • 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.

  1. Make sure you use the Spring hibernate4 classes:

    org.springframework.orm.hibernate4.HibernateTransactionManager
    

  2. Don't override @Transactional methods, but use a template patterns instead.

  3. Try using JPATransactionManager instead so you can inject the current EntityManager with the @PersistenceContext annotation instead. This is much more elegant than calling sessionFactory.getCurrentSession() in every DAO method.

这篇关于HibernateException:无法获取当前线程的事务同步会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-11 01:59