Размножение.REQUIRES NEW не создает новую транзакцию весной с JPA

у меня есть следующий сценарий. Я использую 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 также откатывается, что мне не нужно. Мне нужно, чтобы эти два метода (createSampleObject и updateSampleObject) получить сохраняется все время, независимо от того, было ли исключение брошено или нет. Как я могу достичь этого?

, если я anotate методов createSampleObject и updateSampleObject С:
@Transactional(propagation = Propagation.NEVER)

идея заключается в том, что исключение не выдается, и я не исключение. В чем проблема? Анализ журналов я вижу это строка:

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

что означает, что эта транзакция создана, но я не вижу намека на другую транзакцию.

это часть моего файла конфигурации для Spring относительно транзакций

<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"/>

2 ответов


весенние транзакции основаны на прокси. Вот как это работает, когда bean a вызывает транзакцию bean B. A фактически имеет ссылку на прокси-сервер, который делегирует bean B. Этот прокси-сервер запускает и фиксирует/откат транзакции:

A ---> proxy ---> B

в вашем коде транзакционный метод a вызывает другой транзакционный метод A. Поэтому Spring не может перехватить вызов и начать новую транзакцию. Это обычный вызов метода без участия прокси-сервера.

Итак, если вы хотите начать новую транзакцию, метод createSampleObject() должно быть в другом Бобе, введенном в ваш текущий Боб.

это объясняется более подробно в документация.


Я предполагаю, что, поскольку оба метода находятся в одном и том же компоненте, AOP Spring не имеет возможности перехватить вызовы метода create/updateSampleObject. Попробуйте переместить методы в отдельный компонент.