web-dev-qa-db-ja.com

クラスとメソッドで@Transactionalを定義することの違いは何ですか

Case1

@Transactional
public class UserServiceImpl implements UserService {

    ...................
    public void method1(){
        try{
            method2();
        }catch(Exception e){

        }
    }
    public void method2(){

    }
}

Case2

public class UserServiceImpl implements UserService {

    ...................
    public void method1(){
        try{
            method2();
        }catch(Exception e){

        }
    }
    @Transactional
    public void method2(){

    }
}

ケース1で例外が発生するとロールバックは機能しますが、ケース2では機能しません。ケース1に従う場合、パフォーマンスの問題はありますか?

56
Anil Kumar

ケース1では、@ Transactionalが個々のメソッドすべてに適用されます。ケース2の場合、@ Transactionalはmethod1()ではなくmethod2()にのみ適用されます

ケース1:-method1()の呼び出し->トランザクションが開始されます。 method1()がmethod2()を呼び出すとき、新しいトランザクションは開始されていません。

ケース2:-method1()の呼び出し->トランザクションは開始されません。 method1()がmethod2()を呼び出すとき[〜#〜] no [〜#〜]新しいトランザクションが開始されます。これは、同じクラス内からメソッドを呼び出すときに@Transactionalが機能しないためです。別のクラスからmethod2()を呼び出すと機能します。

スプリングリファレンスマニュアル から:

プロキシモード(デフォルト)では、プロキシを介して着信する外部メソッド呼び出しのみがインターセプトされます。つまり、ターゲットオブジェクトの別のメソッドを呼び出すターゲットオブジェクト内のメソッドは、実際には、呼び出されたメソッドが@Transactionalでマークされていても、実行時に実際のトランザクションにつながりません。また、期待される動作を提供するためにプロキシを完全に初期化する必要があるため、初期化コードでこの機能、つまり@PostConstructに依存しないでください。

50
niekname

クラスの_@Transactional_は、サービスの各メソッドに適用されます。ショートカットです。通常、すべてのメソッドがリポジトリレイヤーにアクセスすることがわかっている場合は、サービスクラスに@Transactional(readOnly = true)を設定できます。その後、モデルで変更を実行するメソッドで_@Transactional_を使用して動作をオーバーライドできます。 1)と2)の間のパフォーマンスの問題は不明です。

37
jeromerg

次のクラスがあるとします:

_@Transactional(readOnly = true)
public class DefaultFooService implements FooService {

  public Foo getFoo(String fooName) {
    // do something
  }

  // these settings have precedence for this method
  @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
  public void updateFoo(Foo foo) {
    // do something
  }
}
_

クラスレベルの_@Transactional_注釈は、クラス内のすべてのメソッドに適用されます。

ただし、、メソッドに_@Transactional_の注釈が付けられている場合(updateFoo(Foo foo)など)、これはトランザクション設定よりも優先されますクラスレベルで定義されます。

詳細:

19

ここ からの引用

Springチームの推奨事項は、インターフェイスに注釈を付けるのではなく、@ Transactional注釈を使用して具体的なクラスにのみ注釈を付けることです。

このメカニズムはプロキシに基づいているため、プロキシを介して着信する「外部」メソッド呼び出しのみがインターセプトされます。つまり、呼び出されたメソッドが@Transactionalでマークされていても、「自己呼び出し」、つまりターゲットオブジェクト内のメソッドがターゲットオブジェクトの他のメソッドを呼び出すと、実行時に実際のトランザクションにつながりません!

17
mok