[英]Transaction required exception JPA / Spring
我在存储库类中有一个方法标记为@Transactional
,方面正在执行,如堆栈跟踪中所见,但抛出的异常是“需要事务处理的异常”
我改变了@Repository
注释@Component
(和它seemd喜欢它固定在某些情况下,这个问题),但它仍然是在网络上的角色发生。
这是堆栈跟踪:
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)
这是抛出异常的代码:
@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
配置:
电磁场:
<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" />
我真的很疯狂,任何帮助都会很棒。
作为一个说明,这一切工作完全没有在我的开发环境(Windows,理念Tomcat的8,JDK 8.0.31(Oracle的),但它提出了在Amazon EC2上Elasticbeanstalk(8 Tomcat的这个错误,64位Linux的亚马逊2015.03,打开JDK 8.0。 31(也尝试使用 Oracle 的 8.0.40)
编辑:更多信息:在整个过滤器链末尾的过滤器上引发异常。
以下是异常前的一些调试信息:
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 层),然后由于异常回滚事务“需要交易”。
这太疯狂了。
编辑嗯,我发现这一行调试:
2015-04-13 15:27:44,074 [http-bio-8080-exec-2] 调试 org.springframework.orm.jpa.JpaTransactionManager - 参与交易失败 - 将现有交易标记为仅回滚
这里的值是:propagation=REQUIRED,isolation=DEFAULT
好像有一个事务,被检查为完成,加入事务失败,所以标记为仅回滚,因为它无法加入它。
我更改了注释驱动的配置,仅通过添加
proxy-target-class="true"似乎已经解决了我们的环境之一 (ap-southeast) 中的问题,即亚马逊上海,但至于欧洲 (eu-west) ,问题依旧。
这是一场噩梦,所有的配置都完全一样(只是指向不同的db & s3)
<tx:annotation-driven mode="aspectj" proxy-target-class="true" transaction-manager="transactionManager" />
解决方案:
毕竟,我终于得到了一些东西。 这修复了它(至少在表面上是这样)。
原因:显然是与spring初始化有关,在初始化完成之前安排了一些任务,有些事情搞砸了。
我使用 REQUIRES_NEW 传播在服务层设置事务注释,以强制创建新事务。
@Transactional(propagation = Propagation.REQUIRES_NEW)
从 DAO 层中删除了@Transactional
。
我还必须对连接器进行一些更改,增加 maxThreads 和 max/min 备用线程。
我还将所有@Scheduled 初始化任务更改为在 tomcat 启动后 10 分钟开始
在所有这些更改之后,错误消失了。
注释我还删除了之前的更改:“ proxy-target-class="true" ”,它仍然可以正常工作,因此这里不是一个很好的修复,但它可能对您有用,就像对我一样某些情况下(后台任务)。
作为旁注,我必须做的另一个更改是将@Repository
更改为@Component
,因为某些事务没有在计划任务上写入数据库。
不是春季专家,但希望这会有所帮助。
几天前,我阅读了类似问题的Spring 文档,我发现:
特别是,您不需要一个应用程序服务器仅仅用于通过 EJB 进行声明性事务。 事实上,即使您的应用程序服务器具有强大的 JTA 功能,您也可能认为 Spring Framework 的声明式事务提供了比 EJB CMT更强大的功能和更高效的编程模型。
AFAIK,在我们的服务中,我们更具体地声明交易以避免一些此类问题,例如:
@Transactional
(
propagation = Propagation.REQUIRED,
readOnly = false,
rollbackFor = Throwable.class
)
如果您的注解仅在某些服务器上有效,请在声明时尽量具体以涵盖您的交易场景。 通过这种方式,我想您将在所有服务器中实现相同的行为。
我只是遇到了同样的问题。 原来,我试图在动态创建的后台线程中使用全类定义的 EntityManager,这导致了异常。 没有关于此问题的其他错误消息,并且堆栈跟踪指向 query.executeUpdate(),因此对此进行排序有点困难。 回到串行处理使错误消失。
我认为这个问题已经在最新版本的 spring 中解决了。 只需在我的服务类之上添加 @Transactional 注释就对我有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.