Propagation.REQUIRES_NEW 不会在 Spring 中使用 JPA 创建新事务 [英] Propagation.REQUIRES_NEW does not create a new transaction in Spring with JPA

查看:34
本文介绍了Propagation.REQUIRES_NEW 不会在 Spring 中使用 JPA 创建新事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下场景.我正在使用 JPA,Spring:

I have the following scenario. I am using JPA, Spring:

@Autowired
SampleService service;

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void PerformLogic(LogicData data) throws SIASFaultMessage
{
    SampleObject so = createSampleObject();

    try{
        .//do some logic to persist things in data
        .
        .
        persistData(data);
        .
        .
        .


        updateSampleObject(so);     
    }
    catch(Exception){
        updateSampleObject(so);     
        throw new SIASFaultMessage();
    }

}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public createSampleObject()
{
    SampleObject so = new SampleObject();

    .
    .//initialize so
    .

    service.persist(so);        
    return so;
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public updateSampleObject(SampleObject so)
{               
    service.persist(so);        
    return so;
}

当一切正常时,数据会毫无问题地保存在数据库中.但是,当抛出异常时,我需要方法 updateSampleObject(so) 将信息保存在数据库中.这不是正在发生的事情.如果抛出异常,方法 updateSampleObject 也会回滚,这不是我需要的.我需要这两个方法(createSampleObjectupdateSampleObject)一直保持下去,无论是否有异常被抛出与否.我怎样才能做到这一点?

When everything works fine, data is persisted in database without problems. However, when an exception is thrown, I need that the method updateSampleObject(so) persist the information in the database. This is not what is happening. If an exception is thrown the method updateSampleObject gets rolled back also, which is not what I need. I need that these two methods (createSampleObject and updateSampleObject) get persisted all the time, no matter whether an exception got thrown or not. How can I achieve this?

此外,如果我对 createSampleObjectupdateSampleObject 方法进行注释:

Moreover, if I anotate the methods createSampleObject and updateSampleObject with:

@Transactional(propagation = Propagation.NEVER)

这个想法是抛出异常并且我没有抛出异常.哪里有问题?分析日志我看到这一行:

the idea is that an exception is thrown and I get no exception thrown. Where is the problem? Analizing the logs I see this line:

org.springframework.orm.jpa.JpaTransactionManager  ==> Creating new transaction with name [com.test.PerformLogic]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT....

这意味着此交易已创建,但我看不到其他交易的任何提示.

which means this transaction is created, but I see no hint of the other transaction.

这是我关于事务的 Spring 配置文件的一部分

This is the part of my configuration file for Spring regarding transactions

<bean id="myDataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>
<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="packagesToScan" value="cu.jpa"/>
    <property name="persistenceProviderClass" value="org.hibernate.ejb.HibernatePersistence"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">${hdm2ddl.auto}</prop>
        </props>
    </property>
    <property value="/META-INF/jpa-persistence.xml" name="persistenceXmlLocation"/>
    <property name="persistenceUnitName" value="jpaPersistenceUnit"/>
</bean>

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

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

推荐答案

Spring 事务是基于代理的.下面是当 bean A 导致 bean B 的事务时它是如何工作的.A 实际上有一个对代理的引用,该代理委托给 bean B.这个代理是启动和提交/回滚事务的代理:

Spring transactions are proxy-based. Here's thus how it works when bean A causes a transactional of bean B. A has in fact a reference to a proxy, which delegates to the bean B. This proxy is the one which starts and commits/rollbacks the transaction:

A ---> proxy ---> B

在你的代码中,A的一个事务方法调用了A的另一个事务方法,所以Spring无法拦截调用并开始一个新的事务.这是一个不涉及任何代理的常规方法调用.

In your code, a transactional method of A calls another transactional method of A. So Spring can't intercept the call and start a new transaction. It's a regular method call without any proxy involved.

所以,如果你想要一个新的事务开始,方法 createSampleObject() 应该在另一个 bean 中,注入到你当前的 bean 中.

So, if you want a new transaction to start, the method createSampleObject() should be in another bean, injected into your current bean.

这在 文档.

这篇关于Propagation.REQUIRES_NEW 不会在 Spring 中使用 JPA 创建新事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆