java 事务需要异常 JPA / Spring
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29601028/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Transaction required exception JPA / Spring
提问by Juan Carrey
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"
我在存储库类中有一个方法标记为@Transactional
,方面正在执行,如堆栈跟踪中所见,但抛出的异常是“需要事务处理的异常”
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.
我将@Repository
注释更改为@Component
(并且在某些情况下似乎解决了这个问题),但它仍然发生在 web 角色上。
Here is the 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_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)
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();
}
Transactional annotation comes from org.springframework.transaction.annotation.Transactional
事务注解来自 org.springframework.transaction.annotation.Transactional
Versions:
版本:
Spring: 4.1.5.RELEASE
Hibernate: 4.3.8.Final
Aspectj: 1.8.5
Tomcat 8.0.20
Configurations:
配置:
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>
Transactions:
交易:
<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.
我真的很疯狂,任何帮助都会很棒。
As a note, this all works perfectly fineon 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)
作为一个说明,这一切工作完美的罚款对我的开发环境(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)
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
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".
这实际上是说,它已经创建了事务,然后加入了事务(现在有两个 @Transactionals,一个在服务层,另一个在 DAO 层),然后由于异常而回滚事务“需要交易”。
This is nuts.
这太疯狂了。
EDITWell, I found this line of debug:
编辑嗯,我发现这一行调试:
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
2015-04-13 15:27:44,074 [http-bio-8080-exec-2] 调试 org.springframework.orm.jpa.JpaTransactionManager - 参与交易失败 - 将现有交易标记为仅回滚
The values here are: propagation=REQUIRED, isolation=DEFAULT
这里的值是: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.
好像有一个事务,被检查为完成,加入事务失败,所以它标记为仅回滚,因为它无法加入它。
采纳答案by Juan Carrey
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)
我更改了注释驱动的配置,仅通过添加proxy-target-class="true"似乎已经解决了我们的环境之一 (ap-southeast) 中的问题,即亚马逊上海,但至于欧洲 (eu-west) ,问题依旧。这是一场噩梦,所有的配置都完全一样(只是指向不同的db & s3)
<tx:annotation-driven mode="aspectj" proxy-target-class="true" transaction-manager="transactionManager" />
<tx:annotation-driven mode="aspectj" proxy-target-class="true" transaction-manager="transactionManager" />
SOLUTION:
解决方案:
I finally got something, after all. This fixes it (at least apparently).
毕竟,我终于得到了一些东西。这修复了它(至少在表面上是这样)。
Reason:Apparently it as something to do with spring initialization, and scheduling some tasks before the initialization has finished, and something got messed up.
原因:显然是与spring初始化有关,在初始化完成之前安排了一些任务,有些事情搞砸了。
I set the transactional annotation at the service layer with a REQUIRES_NEW propagation, to force a new transaction to be created.
我使用 REQUIRES_NEW 传播在服务层设置事务注释,以强制创建新事务。
@Transactional(propagation = Propagation.REQUIRES_NEW)
Removed the @Transactional
from the DAO layer.
@Transactional
从 DAO 层中删除了。
I also had to make some changes to the connector, incrementing maxThreads and max/min spare threads.
我还必须对连接器进行一些更改,增加 maxThreads 和 max/min 备用线程。
I also changed all my @Scheduled initialization tasks to start 10 minutes after tomcat start
我还将所有@Scheduled 初始化任务更改为在 tomcat 启动后 10 分钟开始
After all this changes, the error went away.
在所有这些更改之后,错误消失了。
NotesI 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).
注释我还删除了之前的更改:“proxy-target-class="true"”,它仍然可以正常工作,因此这里并不是一个很好的解决方案,但它可能对您有用,就像对我一样某些情况下(后台任务)。
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.
作为旁注,我必须做的另一个更改是更改@Repository
为@Component
,因为某些事务没有在计划任务上写入数据库。
回答by Jordi Castilla
Not an expert in spring, but hope this helps.
不是春季专家,但希望这会有所帮助。
Some days ago, reading Spring documentationfor a similar issue, I've found:
几天前,我阅读了类似问题的Spring 文档,我发现:
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 powerand a more productive programming model than EJB CMT.
特别是,您不需要应用程序服务器来仅用于通过 EJB 的声明性事务。事实上,即使您的应用程序服务器具有强大的 JTA 功能,您也可能认为 Spring Framework 的声明式事务提供了比 EJB CMT更强大的功能和更高效的编程模型。
AFAIK, in our services, we declare transactions more specific to avoid some of this problems like:
AFAIK,在我们的服务中,我们更具体地声明交易以避免一些此类问题,例如:
@Transactional
(
propagation = Propagation.REQUIRED,
readOnly = false,
rollbackFor = Throwable.class
)
If your annotations works ONLY in some servers, try to be specific when declaring it in order to cover your transaction scenario. In this way I guess you will achieve same behaviour in all servers.
如果您的注解仅在某些服务器上有效,请在声明时尽量具体以涵盖您的交易场景。通过这种方式,我想您将在所有服务器中实现相同的行为。
回答by Balin
I just had the very same problem. Turned out, that I tried to use the class-wide defined EntityManager in a background thread created on the fly, and that caused the exception. There were no other error messages regarding this issue, and the stacktrace pointed to query.executeUpdate(), so it was a bit difficult to sort this out. Going back to serial processing made the error vanish.
我只是遇到了同样的问题。原来,我试图在动态创建的后台线程中使用全类定义的 EntityManager,这导致了异常。没有关于此问题的其他错误消息,并且堆栈跟踪指向 query.executeUpdate(),因此对此进行排序有点困难。回到串行处理使错误消失。