简体   繁体   English

Spring 4 + Hibernate中的入门bean的事务管理

[英]Transaction management for starter bean in Spring 4 + Hibernate

In my Spring MVC + Hibernate app I have XML-configured started bean: 在我的Spring MVC + Hibernate应用程序中,我具有XML配置的启动bean:

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

I've also configured transaction management: 我还配置了事务管理:

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

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

And CreateDefaultUserBean has autowired SessionFactory : 并且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();
         // ...
    }
}

So it fails with Could not obtain transaction-synchronized Session for current thread exception: 因此它失败, Could not obtain transaction-synchronized Session for current thread异常的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)

What am I doing wrong? 我究竟做错了什么?

As workaround I've found that I can just openSession() instead of using currentSession() : 作为解决方法,我发现我可以只使用openSession()而不是使用currentSession()

Session session = sessionFactory.openSession();

In this case @Transactional annotation is also useless. 在这种情况下,@ @Transactional注释也没有用。 This doesn't explain why does Could not obtain transaction-synchronized Session for current thread exception occur in described configuration, but helps obtain desired result. 这不能解释为什么在所描述的配置中Could not obtain transaction-synchronized Session for current thread异常Could not obtain transaction-synchronized Session for current thread ,但却有助于获得所需的结果。

  • the current session is created and bound to current thread using a dedicated aspect applied on @Transactionnal annotated methods. 当前会话是使用应用于@Transactionnal注释方法的专用方面创建并绑定到当前线程的。
  • Spring aspects use JDK / cglib dynamic proxies Spring方面使用JDK / cglib 动态代理
  • Dynamic proxies have the same contract that the proxied object and encapsulate it. 动态代理与被代理对象具有相同的契约并对其进行封装。 when Spring injects you a bean, it injects the proxy in place of the raw object 当Spring向您注入bean时,它将注入代理代替原始对象

So Spring builds your bean (using the default constructor and an eventual init method) then encapsulates it in a proxy and inject the proxy in place of the bean. 因此,Spring会构建您的bean(使用默认构造函数和最终的init方法),然后将其封装在一个代理中,然后将代理注入到bean中。 the init method is so invocated directly and transactionnal aspects is not applied ; 直接调用init方法,不应用事务方面; there isn't so any current session nor transaction available at this point. 目前尚无任何当前会话或事务可用。

Same problem and workaround than here @Transactional on @PostConstruct method @PostConstruct方法上的@Transactional相同的问题和解决方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 休眠/春季交易管理问题 - Issue with hibernate/Spring transaction management Spring 4 + Hibernate 4事务管理错误 - Spring 4 + Hibernate 4 transaction management error 事务管理Spring 3-Hibernate 3.5 - Transaction management spring 3 - hibernate 3.5 使用Spring和Hibernate进行事务管理会导致非活动事务 - Transaction management with Spring and Hibernate make inactive transactions 多个数据库的事务管理使用Spring和Hibernate - Transaction management for multiple database Using Spring & Hibernate Spring事务管理:无法解析bean&#39;transactionManager&#39;的引用 - Spring transaction management: Cannot resolve reference to bean 'transactionManager' 如何为部署到WAS 8的Spring 4 / Hibernate 4.3应用程序配置事务管理 - How to configure transaction management for spring 4/hibernate 4.3 app deployed to WAS 8 将Hibernate和Spring结合使用时,事务管理的最佳实践是什么? - What is the best practice for transaction management when using Hibernate and Spring together? 如何将 Spring 事务管理与 Hibernate 集成? - How can I integrate Spring transaction management with Hibernate? Hibernate 和 Spring3 事务管理注释-配置问题:休眠异常:没有 Hibernate Session 绑定到线程 - Hibernate and Spring3 Transaction Management Annotation-Configuration problems: Hibernate-Exception: No Hibernate Session bound to thread
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM