1

以前我在 com.TestTransaction 类中创建了一个方法 updateRecord() 。updateRecord() 方法有一个用于将值插入数据库的 for 循环。如果循环内抛出任何异常,所有插入的值都将回滚。这工作正常,代码如下:

在java类文件里面

public class com.TestTransaction{
   ...
   //this is a big transaction
   public void updateRecord(){
      for(int i=0;i<5;i++){
         //insert value to database...
         //...if a runtime exception thrown here,
         //updateA() method will rollback as a whole transaction,
         //so all updates which were done inside the loop will rollback
      }
   }
   ...
}

内部 config.xml 文件(Spring 配置文件)

<bean id="masterTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
   <property name="dataSource" ref="masterDataSource" />
   <property name="nestedTransactionAllowed" value="true" />
</bean>
...
<aop:config proxy-target-class="true">
   <aop:pointcut id="testTransactionTX" expression="execution(* com.TestTransaction.*(..))"/>
   <aop:advisor pointcut-ref="testTransactionTX" advice-ref="defaultTxAdvice"/>
</aop:config>
...
<tx:advice id="defaultTxAdvice" transaction-manager="masterTxManager">
   <tx:attributes>
      <tx:method name="update*" propagation="REQUIRED"/>
   </tx:attributes>
</tx:advice>

然后我决定在 updateRecord() 方法的循环中编写代码作为单独的方法 doUpdateRecord()。这样当 doUpdateRecord() 抛出 RuntimeException 时,它只会回滚这个 doUpdateRecord() 并且所有之前的更新都会被提交。但它似乎无法回滚。

代码如下:

public class com.TestTransaction{
   ...
   //this is no longer a big transaction
   public void updateRecord(){
      for(int i=0;i<5;i++){
         //every doUpdateRecord() call will start a new transaction
         doUpdateRecord();
      }
   }

   //this is a transaction
   public void doUpdateRecord(){
         //insert value to database...
         //...if a runtime exception thrown here,
         //it only rollback this method
   }
}

弹簧配置文件:

<bean id="masterTxManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
       <property name="dataSource" ref="masterDataSource" />
       <property name="nestedTransactionAllowed" value="true" />
    </bean>
    ...
    <aop:config proxy-target-class="true">
       <aop:pointcut id="testTransactionTX" expression="execution(* com.TestTransaction.doUpdateRecord(..))"/>
       <aop:advisor pointcut-ref="testTransactionTX" advice-ref="defaultTxAdvice"/>
    </aop:config>
    ...
    <tx:advice id="defaultTxAdvice" transaction-manager="masterTxManager">
       <tx:attributes>
          <tx:method name="*" propagation="REQUIRES_NEW"/>
       </tx:attributes>
    </tx:advice>

任何人都可以对正在发生的事情给出任何想法吗?在循环内调用方法(事务)时是否可以回滚一次更新?

4

2 回答 2

0

因为spring只支持知道你的方法调用的方面,所以spring将无法拦截doUpdateRecord,因为它没有针对bean的spring托管实例调用。为了使方面工作,需要针对 spring bean 实例调用 doUpdateRecord,因为只有这样,spring 才能拦截方法调用并插入事务性内容。

要么将 TestTransaction 的 spring bean 实例注入测试事务本身并在调用 doUpdateRecord 时引用它(不确定这是否会起作用),要么将 doUpdateRecord 代码移动到另一个 bean 并针对该 bean 调用。

于 2011-11-28T12:40:30.823 回答
0

这可能是我在这个问题中遇到的情况。同一类中的调用不会通过代理,并且您的切入点逻辑将被忽略。

于 2011-11-28T11:55:24.200 回答