Как определить транзакции отката, которые вызываются внутри цикла с помощью Spring AOP? - PullRequest
1 голос
/ 28 ноября 2011

Ранее я создал метод updateRecord () в классе com.TestTransaction.Метод 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
   }
}

Файл конфигурации 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>

Кто-нибудь может дать какие-либо идеи о том, что происходит?Можно ли откатить одно обновление, когда метод (транзакция) вызывается внутри цикла?

Ответы [ 2 ]

0 голосов
/ 28 ноября 2011

Поскольку spring поддерживает только те аспекты при вызове метода, которые знают о вас, Spring не сможет перехватить этот doUpdateRecord, поскольку он не был вызван для экземпляра bean, управляемого Spring. Чтобы аспект работал, нужно вызвать doUpdateRecord для экземпляра пружинного компонента, потому что только тогда он может перехватить вызов метода и вставить транзакционный материал.

Либо вы вставляете экземпляр bean-компонента SpringTransaction в саму тестовую транзакцию и ссылаетесь на него, когда вызываете doUpdateRecord (не уверен, что это сработает), либо перемещаете код doUpdateRecord в другой бин и вызываете этот бин.

0 голосов
/ 28 ноября 2011

Возможно, я сталкивался с этим вопросом .Вызовы в одном и том же классе не проходят через прокси, и ваша логика pointcut игнорируется.

...