交易需要例外JPA / Spring

我在存储库类中有一个标记为@Transactional ,正在堆栈跟踪中看到正在执行的方面,但抛出的exception是“Transaction required exception”

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

这是堆栈跟踪:

 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) 

以下是抛出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

版本:

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

配置:

EMF:

        

交易方式:

     

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

请注意,这一切在我的开发环境(Windows,Idea Tomcat 8,JDK 8.0.31(Oracle))上完全正常 ,但它在Amazon EC2 Elasticbeanstalk(Tomcat 8,64位Amazon Linux 2015.03,Open JDK 8.0)上引发了此错误。 31(试图从Oracle使用8.0.40)

编辑 :更多信息:在整个filter链的末尾,filter抛出exception。

以下是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 

实际上,它创建了事务,然后它加入了事务(现在有两个@Transactionals,一个在服务层,另一个在DAO层),然后由于exception“它回滚事务”需要交易“。

这很坚果。

编辑嗯,我找到了这行调试:

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

这里的值是:propagation = REQUIRED,isolation = DEFAULT

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

我更改了注释驱动的配置,只需添加proxy-target-class =“true”似乎已解决了我们在亚马逊上海的某个环境(东南部),但欧洲(欧洲西部)的问题,问题仍在发生。 这是一场噩梦,所有配置完全相同(它只指向不同的db和s3)

  

解:

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

原因:显然它与Spring初始化有关,并且在初始化完成之前调度一些任务,并且搞砸了。

我在服务层使用REQUIRES_NEW传播设置事务注释,以强制创建新事务。

 @Transactional(propagation = Propagation.REQUIRES_NEW) 

从DAO图层中删除了@Transactional

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

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

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

注意我还删除了之前的更改:“ proxy-target-class =”true“ ”,它仍然正常工作,所以这里不是一个很好的解决方案,但它可能对你有用,就像它对我一样一些情况(后台任务)。

正如旁注所示,我必须做的另一个改变是将@Repository更改为@Component ,因为有些事务没有在计划任务上写入DB。

spring不是专家,但希望这会有所帮助。

几天前,阅读Spring文档中的类似问题,我发现:

特别是,您不需要仅通过EJB进行声明式事务的应用程序服务器。 实际上, 即使您的应用程序服务器具有强大的JTAfunction,您也可以决定Spring Framework的声明性事务提供比EJB CMT 更强大的function和更高效的编程模型。

AFAIK,在我们的服务中,我们声明交易更具体,以避免一些问题,如:

 @Transactional ( propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Throwable.class ) 

如果您的注释仅适用于某些服务器,请在声明注释时尝试具体说明以覆盖您的事务方案。 通过这种方式,我猜你将在所有服务器中实现相同的行为。