繁体   English   中英

事务需要异常 JPA / Spring

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM