我在存储库类中有一个标记为@Transactional
的方法,正在堆栈跟踪中看到正在执行的方面,但抛出的异常是“Transaction required exception”
我将@Repository
注释更改为@Component
(似乎它在某些情况下解决了这个问题),但它仍然发生在网络角色上。
这是stacktrace:
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
配置:
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" />
我真的很疯狂,任何帮助都会很棒。
请注意,这一切在我的开发环境(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)
编辑 :更多信息:在整个过滤器链末尾的过滤器上抛出异常。
以下是异常之前的一些调试信息:
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,174 [http-bio-8080-exec-2] DEBUG org.springframework.orm.jpa.JpaTransactionManager - 参与交易失败 - 将现有交易标记为仅回滚
这里的值是:propagation = REQUIRED,isolation = DEFAULT
似乎有一个事务被检查为已完成,并且加入事务失败,因此它将其标记为仅回滚,因为它无法加入它。
答案 0 :(得分:5)
我更改了注释驱动的配置,只需添加 proxy-target-class =&#34; true&#34; 似乎修复了我们在亚马逊上海的一个环境(东南部)问题,但对于欧洲(欧洲西部),问题仍然存在。这是一场噩梦,所有配置完全相同(它只指向不同的db&amp; s3)
<tx:annotation-driven mode="aspectj" proxy-target-class="true" transaction-manager="transactionManager" />
击> <击> 撞击>
<强> SOLUTION:强>
毕竟,我终于得到了一些东西。这解决了它(至少显然)。<强>原因:强> 显然它与spring初始化有关,在初始化完成之前调度一些任务,并且搞砸了。
我使用REQUIRES_NEW传播在服务层设置事务注释,以强制创建新事务。
@Transactional(propagation = Propagation.REQUIRES_NEW)
从DAO图层中删除了@Transactional
。
我还必须对连接器进行一些更改,增加maxThreads和max / min备用线程。
我还将所有@Scheduled初始化任务更改为在tomcat启动后10分钟启动
在所有这些改变之后,错误就消失了。
<强> 备注 强> 我还删除了之前的更改:&#34; proxy-target-class =&#34; true&#34; &#34;,它仍然正常工作,因此它们不是这真的是一个很好的解决方案,但它可能对你有用,就像它在某些情况下(背景任务)一样。
正如附注所示,我必须做的另一项改变是将@Repository
更改为@Component
,因为有些交易没有对数据库进行写入操作预定的任务。
答案 1 :(得分:3)
春天不是专家,但希望这有帮助。
前几天,在Spring documentation阅读类似问题时,我发现:
特别是,您不需要仅通过EJB进行声明式事务的应用程序服务器。事实上,即使你的应用服务器具有强大的JTA功能,你也可以决定Spring Framework的声明式事务提供更强大的功能,并且比EJB CMT更高效的编程模型。
AFAIK,在我们的服务中,我们声明交易更具体,以避免一些问题,如:
@Transactional
(
propagation = Propagation.REQUIRED,
readOnly = false,
rollbackFor = Throwable.class
)
如果您的注释仅适用于某些服务器,请在声明注释时尝试具体说明,以便涵盖您的交易方案。通过这种方式,我猜你将在所有服务器中实现相同的行为。
答案 2 :(得分:1)
我只是遇到了同样的问题。原来,我试图在动态创建的后台线程中使用全类定义的EntityManager,这导致了异常。没有关于此问题的其他错误消息,并且stacktrace指向query.executeUpdate(),因此很难解决这个问题。回到串行处理使错误消失。
答案 3 :(得分:0)
我认为这个问题在最新版本的spring中已经解决。只需在我的服务类顶部添加@Transactional批注对我来说是有效的。