2012-03-29 19 views
14

抽象クラスからコア機能を継承する一連の@Serviceがあります。私は@Service@Transactionalという具体的なサブクラスサービスをそれぞれマークしました。抽象スーパークラスには、これらの各サービスの公開エントリポイントメソッドが含まれています。換言すれば、私は、次のようなものがある:Spring @トランザクションの継承規則

abstract class AbstractService { 

    public void process() { 
     // Do common initialisation code here 
     processSpecific(); 
     // Do common completion code here 
    } 

    abstract protected void processSpecific(); 
} 


@Service @Transactional 
public class FirstSpecificService extends AbstractService { 
    protected void processSpecific() { 
     // Do specific processing code here 
    } 
} 


@Service @Transactional 
public class SecondSpecificService extends AbstractService { 
    protected void processSpecific() { 
     // Do different specific processing code here 
    } 
} 

各具象サブクラスのサービスに固有のコードは、トランザクションの伝搬としてREQUIREDを有するデータベースに変更を加えるためにDAO層に複数の呼び出しを行いますタイプ。

上記のように定義されたサービスでは、これらの具体的なサブクラスサービスのコード内に現在のトランザクションがなく、DAOレイヤーへの各呼び出しで新しいトランザクションが作成され、トランザクションをコミットして戻ります。私は@Transactionalと抽象スーパークラスに注釈を付ける場合

しかし、そのトランザクションが正しく作成さであり、DAO層にサブの呼び出しはすべて、現在のトランザクションに参加しています。

私の質問は、@Transactionalの動作を継承するためのルールは何ですか? Springが実際にインスタンス化している具体的なサブクラスサービスで@Transactionalを使用しないのはなぜですか?この場合、@Transactionalはスーパークラスにある必要があります。なぜなら、これは公開エントリーポイント方式がどこにあるのかということです。

+0

ちなみに、[関連するSpringSourceのドキュメント](http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework)を見てきました。 -reference.html#transaction-declarative-annotations)、これはこれをカバーしていないようです。 – DuncanKinnear

答えて

9

注:(デフォルト)プロキシモードでは、プロキシ経由で着信したコール のみ「外部」方法が傍受されます。これは、 'self-invocation'、つまりターゲットオブジェクト内のメソッド 他のメソッドを呼び出しても、呼び出されたメソッドが@Transactionalでマークされていても、実行時に実際のトランザクション につながることはありません。

あなたの具体的な実装に@Transactionalを持っていて、実際に自分の注釈でトランザクションされたプロセスメソッドを呼び出しているが、あなたのサブクラスにprocessSpecificを呼び出す処理方法が原因で、この内部コールのトランザクションされていないにもかかわらず。

Looking Weaving。

+0

しかし、プロキシは 'FirstSpecificService'のインスタンスではありませんか?この場合、システムはそのインスタンスの外部 'プロセス'メソッドを呼び出すことになり、インスタンス自体は '@ Transactional'としてマークされます。私は '@ Transactional'とマークされた内部のプライベートメソッドや保護されたメソッドはトランザクションに影響を与えませんが、それは私が持っているものではないことを完全に理解しています。私の全豆は '@ Transactional'とマークされています。 – DuncanKinnear

+0

いいえ、内部メソッドから呼び出された場合、トランザクションにはなりません。外部からプロセスメソッドを呼び出すときには、プロキシインスタンスはトランザクション制御され、processメソッドがprocessSpecificを呼び出すと、サブクラスprocessSpecificではないプロキシオブジェクトに対してポイントカットが行われたため、springはトランザクションに関することを知らない方法。私たちは同じ問題を抱えていました。 – Kathir

+0

上記の私の例に関して、「積み込み時間」を説明してください。これらの(意図された)サンプルサービスのコードはどのように変更されますか? – DuncanKinnear

1

transaction propagationについては、@Transactionalを使用してどのように構成できますか?

もう1つ興味深い点は、annotate concrete classes(注釈インターフェイスとは対照的)であることをSpringが推奨していることです。春のトランザクションのドキュメントから

+0

はい、上記のように、私はドキュメントのすべてのセクションを読んだが、このケースでは適用されていないようです。私の抽象スーパークラスは**インタフェースではなく、実際の具体的なサブクラスによって継承されたコードです。おそらく私の例に当てはまると思う文書のセクションを引用することができます。 – DuncanKinnear

+1

DAOが(サービスによって開始された)既存のトランザクションに常に参加することを確認したい場合は、DAOを@Transactional(propagation = [Propagation.MANDATORY](http://static.springsource.org) /spring/docs/3.1.x/javadoc-api/org/springframework/transaction/annotation/Propagation.html#MANDATORY))、[必須]を使用しているため(http://static.springsource.org/spring/docs/3.1 .x/javadoc-api/org/springframework/transaction/annotation/Propagation.html#REQUIRED)は、存在しない場合は新しいトランザクションを作成します。 – matsev

+0

はい、それは私たちが将来これらの問題をキャッチする方法ですが、引き続き継承ルールが何であるかは説明していません。 – DuncanKinnear

関連する問題