web-dev-qa-db-ja.com

Springトランザクションを理解する-トランザクションメソッドが別のトランザクションメソッドを呼び出すとどうなりますか?

Springトランザクションの動作を理解するために、_@Transactional_とマークされた1つのメソッドが_@Transactional_とマークされた別のメソッドを呼び出す次の場合に何が起こるかを知りたいと思います。

構成がすべてのデフォルト設定を使用すると仮定します。

_@Service("myService")
@Transactional
public MyService{
   public void myServiceMethod(){
      myDAO.getSomeDBObjects();
   }
}

@Repository("myDAO")
@Transactional
public MyDAOWithUsesBeyondMyService{
   public void getSomeDBObjects(){...}
}
_

MyService.myServiceMethod()と入力すると、明らかにトランザクションが開始されます。次に、myDAO.getSomeDBObjects()にドリルダウンすると、どうなりますか?トランザクションがすでに存在するという事実によって、新しいトランザクションが発生することはありませんか、それともここで2つのトランザクションを作成していますか?

Propagationに関するドキュメント(以下に引用)はこれをカバーしているようですが、私の理解を確認したいと思います。私の処女の脳が一度に理解するのは少し大変でした。

Propagation:通常、トランザクションスコープ内で実行されるすべてのコードはそのトランザクションで実行されます。ただし、トランザクションコンテキストがすでに存在する場合に、トランザクションメソッドが実行された場合の動作を指定するオプションがあります。たとえば、コードは既存のトランザクションで実行し続けることができます(一般的なケース)。または、既存のトランザクションを一時停止して、新しいトランザクションを作成することもできます。 Springは、EJBCMTでおなじみのすべてのトランザクション伝播オプションを提供します。 Springでのトランザクション伝播のセマンティクスについては、10.5.7項「トランザクション伝播」を参照してください。

27
David Parks

2つの答え:

a)それをしないでください。サービスレイヤーまたはdaoレイヤーで@Transactionalを使用しますが、両方は使用しません(サービスメソッドごとに1つのトランザクションが必要になる可能性があるため、サービスレイヤーが通常の選択です)。

b)これを行うと、何が起こるかは@Transactionalアノテーションのpropagation属性に依存し、このセクションで説明されています: 10.5.7トランザクション伝播 。基本的に:PROPAGATION_REQUIREDは、両方のメソッドで同じトランザクションが使用されることを意味し、PROPAGATION_REQUIRES_NEWは新しいトランザクションを開始します。

あなたのコメントについて:

もちろん、読み続けて、プロキシを使用しているため、この2番目のメソッドはトランザクションプロキシによって管理されないため、他のメソッド呼び出しと同じであることに気付きました。

これはあなたの状況では当てはまりません(両方のメソッドが同じクラス内にある場合のみ)。

Beanにメソッドabがあり、abを呼び出す場合、bは実際のメソッドで呼び出されます。プロキシ、プロキシ内から呼び出されるため(Beanはそれが外部にプロキシされていることを知りません)。

proxy      bean  
a() -->    a()
            |
            V  
b() -->    b()

ただし、あなたの状況では、サービスにdaoオブジェクトが挿入され、それ自体がプロキシになるため、次のような状況になります。

           proxy      bean
service    a() -->    a()
                       |
             /---------/
             |                 
             V
dao        b() -->    b()
39