【问题标题】:Hibernate 5.2 and Spring 4.3, Non JPA - javax.persistence.TransactionRequiredException: no transaction is in progressHibernate 5.2 和 Spring 4.3,非 JPA - javax.persistence.TransactionRequiredException:没有正在进行的事务
【发布时间】:2017-01-10 01:30:41
【问题描述】:

将我的应用程序从休眠 5.1 升级到 5.2.6 时,我看到以下错误。具体来说,这是春季 4.3.5。

javax.persistence.TransactionRequiredException: no transaction is in progress
org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3450)
org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1418)
org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1414)
org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:144)
org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:95)
org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:932)
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:744)
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730)
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
com.sun.proxy.$Proxy140.mapUserFromContext(Unknown Source)
org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:87)

正如您在下面的堆栈跟踪中看到的那样,spring 显然已经启动了一个事务,并且实际上是在提交事务之前尝试触发刷新。似乎同步休眠和弹簧事务的代码不适用于休眠 5.2(看起来位于 org.springframework.orm.hibernate5.SpringSessionContext.currentSession() 的末尾)。这是一个开放的错误,还是我错过了某个地方的配置?

【问题讨论】:

  • 显然它还没有开始交易,否则不会发生异常。你能添加一些你的配置吗?另外,为什么使用 LDAP 会导致休眠事务异常?!
  • 你在这方面有什么收获吗?我看到了同样的问题(再次肯定有一个事务开始,请注意方法org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction 在调用堆栈上......)。这似乎是一个错误,但only related bug report I can find in Spring's JIRA 显然已在 4.3.3 中修复并发布,因此这里不应该成为问题。
  • 所以,我需要通过它,所以我搬到了org.springframework.transaction.jta.JtaTransactionManager。这按预期工作,允许在多个数据源之间共享单个事务,尽管这有点矫枉过正,因为我们只使用一个数据源。不幸的是,@Jules 建议的 hibernate5.HibernateTransactionManager 经理不适用于我们,因为我们有多个会话工厂,但它可能适合您。

标签: java spring hibernate spring-transactions


【解决方案1】:

在我的例子中,问题是由使用 Spring 的 JDBC TransactionManager 实现的旧配置设置引起的,而不是适当的 Hibernate 集成设置。这对于 Hibernate 4.1 显然是可以接受的,但对于 5.2 则不行。解决方法是将我的事务管理器 bean 声明更改为:

<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="dataSource" ref="dataSource"/>
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

【讨论】:

    【解决方案2】:

    我在升级受 Spring XML 配置支持的遗留应用程序时遇到了同样的问题。

    以下休眠属性必须添加到 Spring LocalSessionFactory 配置中:

    <prop key="hibernate.transaction.coordinator_class">jta</prop>
    <prop key="hibernate.transaction.jta.platform">JBossAS</prop>
    

    原因似乎是在 Hibernate 5.2 中,对于非 JPA 应用程序,hibernate.transaction.coordinator_class 的默认值是 jdbc。这与 Spring 事务不兼容。

    【讨论】:

      【解决方案3】:

      我们面临同样的问题,我找到了不同的原因。

      Spring 4.3.9,Hibernate 5.2.10,带有 XML 配置和声明式事务。 问题是 setReadOnly() 放置在事务中的错误位置,它在 getTransaction() 之后设置

      错误代码:

      DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
      transactionStatus = transactionManager.getTransaction(transactionDefinition);
      transactionDefinition.setReadOnly(true);  //wrongly set it will not set in transactionstatus
      //DAO Call
      transactionManager.commit(transactionStatus);
      

      修改上述代码以解决问题:

      DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
      transactionDefinition.setReadOnly(true);
      transactionStatus = transactionManager.getTransaction(transactionDefinition);
      //DAO Call
      transactionManager.commit(transactionStatus);
      

      【讨论】:

        【解决方案4】:

        当我们将 spring-boot-dependencies 包从 1.5 升级到 2.0.2 时,我遇到了同样的异常(这有效地将 spring 4 升级到 5,并将 hibernate 5.0 升级到 5.2)。

        我有一个标记为 @Transactional 的测试用例,它在内部调用标记为 @Transactional(propagation=Propagation.NOT_SUPPORTED) 的内部方法) 因为它有一些不应该成为上游交易一部分的东西。升级后开始出现以下错误,在 Spring 4 和 Hibernate 5.0 组合下运行良好。

        javax.persistence.TransactionRequiredException: no transaction is in progress
        
        at org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3505)
        at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1427)
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1423)
        at org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:147)
        at org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
        at org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:96)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:922)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:730)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:532)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
        

        通过在不需要事务的方法中添加“readOnly = true”属性来解决 - @Transactional(readOnly = true, propagation=Propagation.NOT_SUPPORTED)强>。似乎较新的版本需要它来指示或作为调用事务子系统的提示。检查readOnly attribute docs。

        另外,请检查接受的答案here 以获得类似的解释。

        【讨论】:

          猜你喜欢
          • 2010-12-20
          • 1970-01-01
          • 2016-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-29
          相关资源
          最近更新 更多