交易需要例外JPA / Spring [英] Transaction required exception JPA / Spring

查看:131
本文介绍了交易需要例外JPA / Spring的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在存储库类中有一个标记为 @Transactional 的方法,正在执行该方面,如堆栈跟踪中所示,但抛出的异常是事务所需的异常

I have a method in the repository class marked as @Transactional, the aspect is being executed as seen in the stacktrace, but the exception being thrown is "Transaction required exception"

我将 @Repository 注释更改为 @Component (似乎它在某些情况下解决了这个问题),但它仍然发生在网络角色上。

I changed the @Repository annotation to @Component (and it seemd like it fixed this problem in some situations), but it is still happening on the web role.

这是堆栈跟踪:

2015-04-13 08:00:56,497 [http-nio-8080-exec-9] WARN  es.mycompany.util.filters.MyFilter - Error storing : /admin/online/update
org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
        at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:410)
        at org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect.ajc$afterThrowing$org_springframework_orm_jpa_aspectj_JpaExceptionTranslatorAspect$1$18a1ac9(JpaExceptionTranslatorAspect.aj:37)
        at es.mycopmany.dao.MyDAO.updateLastUpdatedTs_aroundBody2(MyDAO.java:36)
        at es.mycopmany.dao.MyDAO$AjcClosure3.run(MyDAO.java:1)
        at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:66)
        at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:72)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
        at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:70)
        at es.mycompany.dao.MyDAO.updateLastUpdatedTs(MyDAO.java:31)

在这里是抛出异常的代码:

And here is the code throwing the exception:

    @Transactional
    public void updateLastUpdatedTs(String id, Calendar date) {
        Query query = entityManager.createQuery("update MyEntity set lastUpdatedTs = :ts "
                + " where id= :id");
        query.setParameter("ts", date);
        query.setParameter("id", id);
        query.executeUpdate();
    }

交易注释来自org.springframework.transaction.annotation.Transactional

Transactional annotation comes from org.springframework.transaction.annotation.Transactional

版本:

Spring: 4.1.5.RELEASE 
Hibernate: 4.3.8.Final 
Aspectj: 1.8.5 
Tomcat 8.0.20

配置:

EMF:

<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
        id="entityManagerFactory">
        <property name="persistenceUnitName" value="athena" />
        <property name="dataSource" ref="dataSource" />
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
        </property>
    </bean>

交易:

<bean class="org.springframework.orm.jpa.JpaTransactionManager"
        id="transactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <tx:annotation-driven mode="aspectj" transaction-manager="transactionManager" />

我真的很疯狂,任何帮助都会很棒。

I am going truly nuts with this, any help would be great.

作为一个说明,这一切在我的开发环境(Windows,Idea Tomcat 8,JDK 8.0.31(Oracle))上工作完全正常,但它在亚马逊上引发了这个错误EC2 Elasticbeanstalk(Tomcat 8,64位Amazon Linux 2015.03,Open JDK 8.0.31(试图从Oracle使用8.0.40)

As a note, this all works perfectly fine on my development environment (Windows, Idea Tomcat 8, JDK 8.0.31 (Oracle's), but it raises this error on Amazon EC2 Elasticbeanstalk (Tomcat 8, 64bit Amazon Linux 2015.03, Open JDK 8.0.31 (Tried to use 8.0.40 from Oracle as well)

编辑 :更多信息:在整个过滤器链的末尾,Filter上抛出异常。

Edit: A bit more info: The exception is thrown on a Filter, at the end of the whole filter chain.

这是一些调试异常前的信息:

Here is some debug info before the exception:

2015-04-13 14:57:48,578 [http-bio-8080-exec-7] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [MyService.myMethod]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2015-04-13 14:57:48,578 [http-bio-8080-exec-7] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@33f67ee5] for JPA transaction
2015-04-13 14:57:48,580 [http-bio-8080-exec-7] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@3112368a]
2015-04-13 14:57:48,581 [http-bio-8080-exec-7] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@3193771b] for key [HikariDataSource (HikariPool-1)] to thread [http-bio-8080-exec-7]
2015-04-13 14:57:48,581 [http-bio-8080-exec-7] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [org.springframework.orm.jpa.EntityManagerHolder@497d4e44] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@5019da97] to thread [http-bio-8080-exec-7]
2015-04-13 14:57:48,581 [http-bio-8080-exec-7] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Initializing transaction synchronization
2015-04-13 14:57:48,581 [http-bio-8080-exec-7] TRACE org.springframework.transaction.aspectj.AnnotationTransactionAspect - Getting transaction for [MyService.myMethod]
2015-04-13 14:57:48,581 [http-bio-8080-exec-7] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@497d4e44] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@5019da97] bound to thread [http-bio-8080-exec-7]
2015-04-13 14:57:48,581 [http-bio-8080-exec-7] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Found thread-bound EntityManager [org.hibernate.jpa.internal.EntityManagerImpl@33f67ee5] for JPA transaction
2015-04-13 14:57:48,581 [http-bio-8080-exec-7] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@3193771b] for key [HikariDataSource (HikariPool-1)] bound to thread [http-bio-8080-exec-7]
2015-04-13 14:57:48,581 [http-bio-8080-exec-7] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Participating in existing transaction
2015-04-13 14:57:48,581 [http-bio-8080-exec-7] TRACE org.springframework.transaction.aspectj.AnnotationTransactionAspect - Getting transaction for [MyDao.updateLastUpdatedTs]
2015-04-13 14:57:48,581 [http-bio-8080-exec-7] DEBUG org.springframework.orm.jpa.EntityManagerFactoryUtils - Opening JPA EntityManager
2015-04-13 14:57:48,582 [http-bio-8080-exec-7] DEBUG org.springframework.orm.jpa.EntityManagerFactoryUtils - Registering transaction synchronization for JPA EntityManager
2015-04-13 14:57:48,582 [http-bio-8080-exec-7] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Bound value [org.springframework.orm.jpa.EntityManagerHolder@4f83552c] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@7cc8111c] to thread [http-bio-8080-exec-7]
2015-04-13 14:57:48,608 [http-bio-8080-exec-7] TRACE org.springframework.transaction.support.TransactionSynchronizationManager - Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@4f83552c] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@7cc8111c] bound to thread [http-bio-8080-exec-7]
2015-04-13 14:57:48,608 [http-bio-8080-exec-7] TRACE org.springframework.transaction.aspectj.AnnotationTransactionAspect - Completing transaction for [MyDao.updateLastUpdatedTs] after exception: org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query

实际上说,它有创建了Transaction,然后它加入了事务(现在有两个@Transactionals,一个在服务层,另一个在DAO层),然后由于需要事务的异常而回滚事务。

Which actually says, it has created the Transaction, it then joined the transaction (There are two @Transactionals now, one at the service layer, and the other at the DAO layer), and then it rollsback the transaction, due to an exception "Transaction required".

这很疯狂。

编辑
好​​吧,我找到了这一行调试:

EDIT Well, I found this line of debug:

2015-04-13 15:27:44,174 [http-bio-8080-exec-2] DEBUG org.springframework.orm.jpa.JpaTransactionManager - 参与交易失败 - 将现有交易标记为仅回滚

2015-04-13 15:27:44,074 [http-bio-8080-exec-2] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Participating transaction failed - marking existing transaction as rollback-only

此处的值为:propagation = REQUIRED,isolation = DEFAULT

The values here are: propagation=REQUIRED, isolation=DEFAULT

似乎有一个事务被检查为已完成,并且加入事务失败,因此它将其标记为仅回滚,因为它无法加入它。

Seems that, there is a transaction, which was checked as completed, and joining the transaction failed, so it marks it as rollback only, because it could not join it.

解决方案

我更改了注释驱动的配置,只需添加 proxy-target-class =true 似乎我们在亚马逊上海的一个环境(东南部)修复了这个问题,但对于欧洲(欧洲西部)来说,问题仍然存在。这是一场噩梦,所有配置完全相同(它只指向不同的db& s3)

I changed the annotation-driven config, just by adding proxy-target-class="true" seems to have fixed the issue in one of our environments (ap-southeast) which is Amazon Shanghai, but as for Europe (eu-west), the problem is still happening. This is a nightmare, all the configurations are exactly the same (it just points to different db & s3)

<tx:annotation-driven mode="aspectj" proxy-target-class="true" transaction-manager="transactionManager" />

解决方案:

毕竟,我终于得到了一些东西。这修复了它(至少显然)。

I finally got something, after all. This fixes it (at least apparently).

原因:
显然它与Spring初始化有关,并且安排了一些初始化完成之前的任务,以及搞砸了的东西。

Reason: Apparently it as something to do with spring initialization, and scheduling some tasks before the initialization has finished, and something got messed up.

我在服务层设置了一个带有REQUIRES_NEW传播的事务注释,以强制创建一个新的事务。

I set the transactional annotation at the service layer with a REQUIRES_NEW propagation, to force a new transaction to be created.

@Transactional(propagation = Propagation.REQUIRES_NEW)

从DAO层删除 @Transactional

我还必须对连接器进行一些更改,增加maxThreads和max / min备用线程。

I also had to make some changes to the connector, incrementing maxThreads and max/min spare threads.

我还将所有@Scheduled初始化任务更改为在tomcat后10分钟启动开始

I also changed all my @Scheduled initialization tasks to start 10 minutes after tomcat start

所有这些改变后,错误就消失了。

After all this changes, the error went away.

Notes
我还删除了之前的更改: proxy-target-class =true,它是s直到工作正常,所以这里不是一个好的解决方案,但它可能对你有用,就像它在某些情况下(背景任务)对我一样。

Notes I also removed the previous change: "proxy-target-class="true"", and it is still working fine, so that weren't really a good fix here, but it might work for you as it did for me on some cases (background tasks).

As另外,我必须做的另一项改变就是将 @Repository 更改为 @Component ,因为某些事务没有在计划任务上写入数据库。

As as side note, the other change that I had to do to make this work, was to change @Repository to @Component, as some transactions weren't doing writes to the DB on scheduled tasks.

这篇关于交易需要例外JPA / Spring的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆