Spring @Transactional - javax.persistence.TransactionRequiredException

时间:2011-03-07 13:09:56

标签: spring jta spring-aop transactional

在以下架构中

控制器 - >服务 - > DAO我试图进行服务运营@Transactional

在我的UserService.fooFunction()中调用

Entity e = dao.find(key)
e.setProperty(something)
dao.update(e)

在dao.update(e)结尾处有

em.flush() //EntityManager obtained by @PersistenceContext annotation (injected by spring IoC)

调用flush()会抛出persistenceException:

javax.persistence.TransactionRequiredException No externally managed transaction is currently active for this thread
    at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.throwCheckTransactionFailedException(JTATransactionWrapper.java:86)

我在想法上做得不够,我做错了,任何帮助都会受到赞赏:)

您可以在下面找到我的配置块:

 <bean id="entityManagerFactory"  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="persistenceUnitName" value="myPU" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter" id="eclipselinkVendorAdapter">
        ..
        </bean>
    </property>

</bean>

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">

</bean>
<tx:annotation-driven  transaction-manager="transactionManager"/>

aop part:

    <aop:config>

    <aop:pointcut id="userServiceOperation"
      expression="execution(* org.mypackage.UserServiceImpl.*(..))"/>

    <aop:advisor pointcut-ref="userServiceOperation" advice-ref="txUserServiceAdvice"/>

</aop:config>

<tx:advice id="txUserServiceAdvice">
    <tx:attributes>
        <tx:method name="get*" read-only="true" propagation="REQUIRES_NEW"/>
        <tx:method name="update*" read-only="false" propagation="REQUIRES_NEW"/>
        <tx:method name="*" propagation="REQUIRES_NEW"/>
    </tx:attributes>
</tx:advice>

不存在任何交易注释。部署我的spring应用程序时,可以看到

[<date>] DEBUG support.DefaultListableBeanFactory: Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
[<date>] DEBUG interceptor.NameMatchTransactionAttributeSource: Adding transactional method [get*] with attribute [PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,readOnly]
[<date>] DEBUG interceptor.NameMatchTransactionAttributeSource: Adding transactional method [update*] with attribute [PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT]
[<date>] DEBUG interceptor.NameMatchTransactionAttributeSource: Adding transactional method [*] with attribute [PROPAGATION_MANDATORY,ISOLATION_DEFAULT]

2 个答案:

答案 0 :(得分:4)

关键问题在这里

  

tx:注释驱动仅查找   @Transactional对bean也一样   应用程序上下文定义于。   这意味着,如果你   投入一个   WebApplicationContext for a   DispatcherServlet,它只检查   @Transactional豆在你的   控制器,而不是您的服务。   见第15.2节“The   DispatcherServlet“更多   信息。

将相同的应用程序上下文作为服务的组件扫描解决了问题:)

答案 1 :(得分:1)

您宣布JtaTransactionManager为您的交易管理员。您确定您的程序在支持JTA的环境中运行,例如成熟的应用程序服务器(JBoss,WebSphere,WebLogic等)吗?

如果您没有JTA环境,则需要使用JPATransactionManager代替:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>