如何不回滚以前的方法持久化数据? [英] How not to roll back previous methods persist data?

查看:103
本文介绍了如何不回滚以前的方法持久化数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的DAO界面很简单:

My DAO interface is simple:

import org.springframework.transaction.annotation.Transactional;

@Component
@Transactional
public interface TTestDao {

    @Transactional()
    public void first();

    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public void second() ;

}

ad impl方法:

ad impl methods:

@Override
public void first() {
          entityManager.persist(new TableTest1().setName("data1"));
          this.second();      
}

public void second() {
     entityManager.persist(new TableTest1().setName("data2"));
     throw new RuntimeException(); // it roll backs data2 and data1
}

第一个方法调用第二个方法.第二种方法出错.

First method invokes second method. Error occurs in second method.

此刻,如果我呼叫first(),则所有保留的信息将被回滚.但是为什么会这样呢? second()方法处于新事务中,我需要将第一种方法的数据保留在数据库中.

At the moment, if I call first(), all persisted information will be rolled back. But why does this happen? second() method is in a new transaction, and I need to keep the first method's data in the db.

换句话说,我需要始终保留第一种方法的数据,但仅回滚第二种方法的数据.我想一直写data1.

In the other words, I need to always persist the first method's data, but roll back only second methods data. I want to write data1 always.

我有什么问题吗?

我在SPRING中有这样的数据库配置:

I have such a db configuration in SPRING:

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
    p:driverClassName="oracle.jdbc.driver.OracleDriver" p:url="jdbc:oracle:thin:@127.0.0.1:1521:xe"
    p:username="dev" p:password="****" >
</bean>


<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

    <property name="dataSource" ref="dataSource" />

    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
    </property>

    <property name="jpaProperties">
        <props>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>

<context:component-scan base-package="ge.ddrc.transport.persistance.entity">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository" />
</context:component-scan>


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

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

我的应用程序正在tomcat中运行(如果发出任何声音)

My App is running in tomcat (if it makes any sences)

推荐答案

@StijnGeukens关闭.实际上,Spring确实使用代理来处理事务,并且默认从另一个内部调用一个事务方法不会导致创建新的事务.但是,在这种情况下,传播专门设置为明确

@StijnGeukens is close. Spring does in fact use proxies to handle the transactions, and by default calling one transactional method from within another would not result in a new transaction being created. However, in this case propogation is being specifically set to explicitly require a new transaction being created. There should be 2 transactions being created:

T1: create
    T2: create
    Exception occurs here
    T2: commit
T1: commit

如您所见,异常发生在任一事务到达其提交点之前.由于未在First中处理,因此执行永远不会到达T1的提交点.这将导致顶层事务被回滚.

As you can see, the exception is occurring before either transaction reaches its commit point. Since it isn't handled in First, execution wouldn't ever reach the commit point for T1. That would result in the top-level transaction being rolled back.

但是,有可能您可以在First中处理该异常,但仍然无法正常工作.从我上面链接到的文档中:

However, it is possible that you could handle the exception in First and it still wouldn't work. From the docs I linked to above:

Note: Actual transaction suspension will not work out-of-the-box on all transaction managers. This in particular applies to JtaTransactionManager, which requires the javax.transaction.TransactionManager to be made available it to it (which is server-specific in standard J2EE).

因此,您的propagation=REQUIRES_NEW可能实际上没有按照它说的去做,因为它不喜欢您的TransactionManager.欢迎来到Spring.

So your propagation=REQUIRES_NEW is likely not actually doing what it says it does because it doesn't like your TransactionManager. Welcome to Spring.

更新 JpaTransactionManager 文档:

在JDBC 3.0上,此事务管理器通过以下方式支持嵌套事务: JDBC 3.0保存点.这 但是,AbstractPlatformTransactionManager.setNestedTransactionAllowed(boolean) "nestedTransactionAllowed"标志默认为"false",因为 嵌套事务将仅适用于JDBC连接,而不适用于 JPA EntityManager及其缓存的对象.您可以手动设置 如果要使用嵌套事务进行JDBC访问,请标记为"true" 参与JPA交易的代码(前提是您的JDBC 驱动程序支持保存点).请注意,JPA本身不支持 嵌套交易!因此,不要期望JPA访问代码能够 在语义上参与嵌套事务.

On JDBC 3.0, this transaction manager supports nested transactions via JDBC 3.0 Savepoints. The AbstractPlatformTransactionManager.setNestedTransactionAllowed(boolean) "nestedTransactionAllowed" flag defaults to "false", though, as nested transactions will just apply to the JDBC Connection, not to the JPA EntityManager and its cached objects. You can manually set the flag to "true" if you want to use nested transactions for JDBC access code which participates in JPA transactions (provided that your JDBC driver supports Savepoints). Note that JPA itself does not support nested transactions! Hence, do not expect JPA access code to semantically participate in a nested transaction.

这非常令人困惑,但是我认为这是说,如果设置了所提到的标志,您将能够使用通过JDBC 3.0的功能实现的嵌套事务.因此,请确保您的驱动程序符合该规范.

This is very confusing but I think what it's saying is that if you set the flag mentioned, you will be able to use nested transactions, implemented using a feature of JDBC 3.0. So make sure that your driver meets that specification.

这篇关于如何不回滚以前的方法持久化数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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