事务需要异常 JPA / Spring
Transaction required exception JPA / Spring
我在存储库 class 中有一个标记为 @Transactional
的方法,正如在堆栈跟踪中看到的那样正在执行方面,但抛出的异常是 "Transaction required exception"
我将 @Repository
注释更改为 @Component
(在某些情况下它似乎解决了这个问题),但它仍然发生在网络角色上。
这是堆栈跟踪:
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_JpaExceptionTranslatorAspecta1ac9(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_AbstractTransactionAspecta73e96cproceed(AbstractTransactionAspect.aj:66)
at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect.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_AbstractTransactionAspecta73e96c(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's),但它在 Amazon EC2 Elasticbeanstalk (Tomcat 8, 64bit Amazon Linux 2015.03, Open JDK 8.0.31 (Tried to use 8.0.40 from Oracle as嗯)
编辑:更多信息:异常在整个过滤器链的末尾的过滤器上抛出。
这是异常发生前的一些调试信息:
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,一个在service层,一个在DAO层),然后回滚事务,由于异常 "Transaction required".
这太疯狂了。
编辑
好吧,我找到了这行调试:
2015-04-13 15:27:44,074 [http-bio-8080-exec-2] DEBUG org.springframework.orm.jpa.JpaTransactionManager - 参与事务失败 - 将现有事务标记为仅回滚
这里的值是:propagation=REQUIRED,isolation=DEFAULT
好像有一个事务,检查完成,加入事务失败,所以标记为回滚,因为不能加入。
不是 spring 方面的专家,但希望这对您有所帮助。
几天前,阅读 Spring documentation 类似的问题,我发现:
In particular, you do not need an application server simply for declarative transactions through EJBs. In fact, even if your application server has powerful JTA capabilities, you may decide that the Spring Framework’s declarative transactions offer more power and a more productive programming model than EJB CMT.
据我所知,在我们的服务中,我们会更具体地声明交易以避免某些此类问题,例如:
@Transactional
(
propagation = Propagation.REQUIRED,
readOnly = false,
rollbackFor = Throwable.class
)
如果您的注释仅适用于某些服务器,请在声明时尽量具体,以涵盖您的事务场景。通过这种方式,我猜您将在所有服务器中实现相同的行为。
我更改了注释驱动的配置,只需添加 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
,因为某些事务没有在计划任务。
我刚刚遇到了同样的问题。结果是,我试图在动态创建的后台线程中使用 class-wide 定义的 EntityManager,这导致了异常。没有关于此问题的其他错误消息,堆栈跟踪指向 query.executeUpdate(),因此解决这个问题有点困难。返回串行处理使错误消失。
我认为该问题已在 spring 的最新版本中得到解决。只需在我的服务之上添加 @Transactional 注释 class 对我有用。
我在存储库 class 中有一个标记为 @Transactional
的方法,正如在堆栈跟踪中看到的那样正在执行方面,但抛出的异常是 "Transaction required exception"
我将 @Repository
注释更改为 @Component
(在某些情况下它似乎解决了这个问题),但它仍然发生在网络角色上。
这是堆栈跟踪:
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_JpaExceptionTranslatorAspecta1ac9(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_AbstractTransactionAspecta73e96cproceed(AbstractTransactionAspect.aj:66)
at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect.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_AbstractTransactionAspecta73e96c(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's),但它在 Amazon EC2 Elasticbeanstalk (Tomcat 8, 64bit Amazon Linux 2015.03, Open JDK 8.0.31 (Tried to use 8.0.40 from Oracle as嗯)
编辑:更多信息:异常在整个过滤器链的末尾的过滤器上抛出。
这是异常发生前的一些调试信息:
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,一个在service层,一个在DAO层),然后回滚事务,由于异常 "Transaction required".
这太疯狂了。
编辑 好吧,我找到了这行调试:
2015-04-13 15:27:44,074 [http-bio-8080-exec-2] DEBUG org.springframework.orm.jpa.JpaTransactionManager - 参与事务失败 - 将现有事务标记为仅回滚
这里的值是:propagation=REQUIRED,isolation=DEFAULT
好像有一个事务,检查完成,加入事务失败,所以标记为回滚,因为不能加入。
不是 spring 方面的专家,但希望这对您有所帮助。
几天前,阅读 Spring documentation 类似的问题,我发现:
In particular, you do not need an application server simply for declarative transactions through EJBs. In fact, even if your application server has powerful JTA capabilities, you may decide that the Spring Framework’s declarative transactions offer more power and a more productive programming model than EJB CMT.
据我所知,在我们的服务中,我们会更具体地声明交易以避免某些此类问题,例如:
@Transactional
(
propagation = Propagation.REQUIRED,
readOnly = false,
rollbackFor = Throwable.class
)
如果您的注释仅适用于某些服务器,请在声明时尽量具体,以涵盖您的事务场景。通过这种方式,我猜您将在所有服务器中实现相同的行为。
我更改了注释驱动的配置,只需添加 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
,因为某些事务没有在计划任务。
我刚刚遇到了同样的问题。结果是,我试图在动态创建的后台线程中使用 class-wide 定义的 EntityManager,这导致了异常。没有关于此问题的其他错误消息,堆栈跟踪指向 query.executeUpdate(),因此解决这个问题有点困难。返回串行处理使错误消失。
我认为该问题已在 spring 的最新版本中得到解决。只需在我的服务之上添加 @Transactional 注释 class 对我有用。