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ファイル内(春の構成ファイル)

<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
   }
}

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.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>

誰かが何が起こっているのかについて何か考えを与えることができますか?メソッド(トランザクション)がループ内で呼び出されたときに、1つの更新をロールバックすることは可能ですか?

4

2 に答える 2

0

この質問で出くわしたのはおそらくそうです。同じクラス内の呼び出しはプロキシを通過せず、ポイントカットロジックは無視されます。

于 2011-11-28T11:55:24.200 に答える
0

springは、ユーザーを認識しているメソッド呼び出しのアスペクトのみをサポートするため、SpringはBeanのSpringマネージドインスタンスに対して呼び出されなかったため、そのdoUpdateRecordをインターセプトできません。アスペクトが機能するためには、doUpdateRecordをSpring Beanインスタンスに対して呼び出す必要があります。これは、その場合にのみ、メソッド呼び出しをSpringインターセプトして、トランザクションのものを挿入できるためです。

TestTransactionのスプリングBeanインスタンスをテストトランザクション自体に挿入し、doUpdateRecordを呼び出すときにそれを参照するか(これが機能するかどうかはわかりません)、doUpdateRecordコードを別のBeanに移動して、そのBeanに対して呼び出します。

于 2011-11-28T12:40:30.823 に答える