4

私のサービスクラス。

@Service
@Transactional(value = "transactionManager", readOnly = true, propagation = Propagation.REQUIRED)
public class DeviceServiceImpl{

@Transactional(readOnly = false)
public void blockAllDevices(){

    createSmsDeviceBlock();

}


public void createSmsDeviceBlock(){

    addToLogTables();

    smsService.sendSms();
}


@Transactional(readOnly = false,propagation = Propagation.REQUIRES_NEW)
public void addToLogTables(){
         try {
          //save object with DAO methods...
        } catch (Exception e) {
          throw new ServiceException(ServiceException.PROCESSING_FAILED, e.getMessage(), e);
        }
}

}

私の controller から、サービスメソッド blockAllDevices() が呼び出されます。addToLogTables() メソッドは Propergation.REQUIRED_NEW としてマークされていますが、問題は addToLogTables() メソッドで新しいトランザクションが作成されず、既存のトランザクションが使用されていることです。

私がやりたいことは、 addToLogTables() メソッドのトランザクションは、smsService.sendSms() メソッドを実行する前にコミットする必要があるということです。

ここでの私の問題は、メソッド addToLogTables() メソッドでトランザクションがコミットに失敗した場合、smsService.sendSms() メソッドを実行すべきではありません。

4

1 に答える 1

11

それはPropagation.REQUIRES_NEW問題ではありません。@Transactionalプロキシがどのように機能するかの問題です。

Spring が で注釈が付けられた Bean をプロキシする場合@Transactional、基本的にはそれをプロキシ オブジェクトにラップし、トランザクションを開いた後に委譲します。委任された呼び出しが戻ると、プロキシはトランザクションをコミットまたはロールバックします。

たとえば、あなたの豆は

@Autowired
private DeviceServiceImpl deviceService;

Spring は実際にラッパー プロキシを挿入します。

だからあなたがするとき

deviceService.blockAllDevices();

トランザクション動作を持つプロキシでメソッドを呼び出しています。しかし、blockAllDevices()あなたがやっている

createSmsDeviceBlock();

これは実際には

this.createSmsDeviceBlock();

wherethisはプロキシではなく実際のオブジェクトを参照しているため、トランザクション動作はありません。

これについては、ドキュメントでさらに説明されています。

設計をやり直す必要があります。

于 2014-01-28T14:54:08.487 に答える