Spring 4 + Hibernate中的starter bean的事务管理

时间:2016-04-05 09:04:38

标签: java spring hibernate spring-mvc transactions

在我的Spring MVC + Hibernate应用中,我有XML配置的启动bean:

<bean name="starter" init-method="create" class="foo.CreateDefaultUserBean" lazy-init="false"/>

我还配置了交易管理:

<tx:annotation-driven transaction-manager="txManager"/>

<bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

CreateDefaultUserBean已自动装配SessionFactory

public class CreateDefaultUserBean {

    @Autowired
    private SessionFactory sessionFactory;

    @Transactional
    public void create() {
        User adminUser = (User) sessionFactory.getCurrentSession().createCriteria(User.class).add(Restrictions.eq("login", username)).uniqueResult();
         // ...
    }
}

因此Could not obtain transaction-synchronized Session for current thread例外失败:

 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'starter' defined in ServletContext resource [/WEB-INF/app-servlet.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:667)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:633)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:681)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:552)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:493)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1238)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1151)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:828)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:135)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1502)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1458)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
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 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1502)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1458)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

我做错了什么?

2 个答案:

答案 0 :(得分:1)

  • 使用@Transactionnal注释方法上应用的专用方面创建当前会话并绑定到当前线程。
  • Spring方面使用JDK / cglib 动态代理
  • 动态代理与代理对象具有相同的契约并将其封装。当Spring为你注入一个bean时,它会注入代理来代替原始对象

所以Spring构建你的bean(使用默认的构造函数和最终的init方法)然后将它封装在代理中并注入代理来代替bean。 init方法是直接调用的,并且不应用transactionnal方面;目前没有任何当前会话和交易可用。

与此处@Transactional on @PostConstruct method

相同的问题和解决方法

答案 1 :(得分:0)

作为解决方法,我发现我可以openSession()而不是使用currentSession()

Session session = sessionFactory.openSession();

在这种情况下,@Transactional注释也是无用的。这并不能解释为什么在描述的配置中发生Could not obtain transaction-synchronized Session for current thread异常,但有助于获得所需的结果。

相关问题