spring事務Propagation及びその実現原理の詳細


本論文で研究したのは主にspring事務Propagationとその実現原理です。
概要
springは今すでにjavaの開発の一つの事実基準です。これはその便利さ、機能がそろっていて、使いやすいという特性のおかげです。開発過程ではDBの操作は非常に一般的であり、dbに関しては事務に関わる。通常の開発過程では気づかなくても、プログラムが正常に実行されても副作用がないということですが、異常があったり、事務がうまく処理されていないと思わぬ結果になる可能性があります。springは事務の面で各種の操作のカプセル化を行って、特に声明式の事務の出現、開発を更に心地良くならせます。springは事務を拡張し、多様な伝播属性を定義することをサポートしています。これも本編で説明するポイントです。
事務は何ですか
厳格でないと、一つの事務は複数の操作の略称で、これらの操作は全部有効になるか、それとも一つも有効にしないか(実行したことがないのと同じ)、一つの汎用的な操作フローは以下のように簡略化されます。

try{
 Connection conn = getConnection();
 //          
}catch(Exception e){
  conn.rollback();
}finally{
 conn.close();
}
上記のコードからいくつかの問題が見られます。
  • 多すぎて不要な固定コード
  • 一つの要求が複数のサービスインターフェースを呼び出す必要がある場合、より詳細な制御トランザクション
  • は困難である。
  • は、jdbc、mybatis、hibernate、jtaなどの様々な底のデータ層にまたがり、符号化方式を統一することが困難である。

  • springは声明式の事務を提供しています。私達は底の具体的な実現に関心を持たなくてもいいです。いろいろな底の実現の細部を遮りました。複雑な業務に対する細かいコントロールをサポートするために、springは事務の伝播属性を提供しています。
    springトランザクション伝搬属性例分析
    Transaction Definitionクラスでは、springは6つの伝播属性を提供し、次にそれぞれ簡単な例で説明する。
    暖かい注意:下記の言及のは現在の事務に参加して、底の階が同一のConnectionを使うので、しかし事務の状態の対象は再び創立することができるので、影響しません。文章で述べた現在は一つの事柄しか存在しません。一つの底のConnectionを共有することを表しています。いくつかのトランザクション状態のオブジェクトが作成されていることを気にしないでください。
    1、PROPAAGATION_REQUIRED
    説明:現在既にトランザクションが存在する場合、このトランザクションに参加します。トランザクションが存在しない場合、トランザクションを作成します。これはデフォルトの伝播属性値です。
    小さな例を見て、コードは以下の通りです。
    
    @Transactional
    public void service(){
     serviceA();
     serviceB();
    }
    
    @Transactional
    serviceA();
    @Transactional
    serviceB();
    serviceAとserviceBはいずれも事務を宣言していますが、デフォルトではpropagation=PROPAAGATION_REQUIREDは、serviceコール全体において、共有されているトランザクションが一つしか存在しません。何か異常が発生した場合、すべての操作がロールバックします。
    2、PROPAAGATION_SUPPORTS
    説明:現在すでに事務が存在しているなら、この事務に加入します。さもなければ、いわゆる空事務を作成します。
    小さな例を見て、コードは以下の通りです。
    
    public void service(){
      serviceA();
      throw new RunTimeException();
    }
    
    @Transactional(propagation=Propagation.SUPPORTS)
    serviceA();
    serviceA実行時には現在事務がありませんので、serviceで投げられた異常はserviceAをロールバックさせません。
    もう一つの例を見てください。コードは以下の通りです。
    
    public void service(){
      serviceA();
    }
    
    @Transactional(propagation=Propagation.SUPPORTS)
    serviceA(){
     do sql 1
     1/0;
     do sql 2
    }
    serviceAが動作していないので、この時、最下のデータソースdefault AutoComit=trueがあれば、sql 1は有効です。default AutoCommt=falseがあれば、sql 1は無効です。service@Transactionタグがあれば、serviceAはserviceの事務を共有します。
    3、PROPAAGATION_MANDATORY
    説明:現在必ず一つの問題が存在しなければならない。
    小さな例を見て、コードは以下の通りです。
    
    public void service(){
      serviceB();
      serviceA();
    }
    serviceB(){
     do sql
    }
    @Transactional(propagation=Propagation.MANDATORY)
    serviceA(){
     do sql 
    }
    このような状況でserviceを実行すると異常が発生します。default AutoCommt=trueであれば、serviceBはロールバックしません。default AutoCommt=falseであれば、serviceBは無効になります。
    4、PROPAAGATN_REQUIRES_NEW
    説明:現在、トランザクションがある場合、現在のトランザクション関連コンテンツを一つのエンティティにカプセル化し、新たに新しいトランザクションを作成し、このエンティティをパラメータとして受け入れ、トランザクションの回復に用いる。より率直に言えば、現在の事務を一時停止し、新しい事務を作成するということです。このような状況に対して、二つの事務は依存関係がなく、新しい事務のロールバックが実現できましたが、外部事務は引き続き実行します。
    小さな例を見て、コードは以下の通りです。
    
    @Transactional
    public void service(){
     serviceB();
     try{
      serviceA();
     }catch(Exception e){
     }
    }
    serviceB(){
     do sql
    }
    @Transactional(propagation=Propagation.REQUIRES_NEW)
    serviceA(){
     do sql 1
     1/0; 
     do sql 2
    }
    serviceインターフェースを呼び出すと、serviceAはREQUIRES_を使用しています。NEWは、新しいビジネスを作成しますが、ServiceAが運転中の異常を投げ出したため、serviceA全体がロールバックされました。service方法では、異常が発生しましたので、serviceBは正常に提出されました。注意してください。serviceのtry...catchコードは必要です。そうでないとserviceも例外を投げて、serviceBもロールバックされます。
    5、Propgations.NOT_SUPPORTED
    説明:現在トランザクションが存在する場合、現在のトランザクションを保留して、そして新しい方法は、トランザクションがない環境で実行され、springトランザクションがない環境でsqlの提出はdefault AutoCommt属性値に完全に依存します。
    小さな例を見て、コードは以下の通りです。
    
    @Transactional
    public void service(){
      serviceB();
      serviceA();
    }
    serviceB(){
     do sql
    }
    @Transactional(propagation=Propagation.NOT_SUPPORTED)
    serviceA(){
     do sql 1
     1/0;
     do sql 2
    }
    serviceメソッドを呼び出したとき、serviceAメソッドの1/0コードを実行したときに、異常を投げました。serviceAは無事務環境にあるため、sql 1が有効かどうかはdefault AutoComitの値によって異なります。default AutoCommt=trueの時にsql 1は有効ですが、service 1は例外を投げて返されます。
    6、PROPAAGATION_NEVER
    説明:現在問題がある場合、異常を投げます。そうでなければ、問題がない環境でコードを実行します。
    小さな例を見て、コードは以下の通りです。
    
    public void service(){
     serviceB();
     serviceA();
    }
    serviceB(){
     do sql
    }
    @Transactional(propagation=Propagation.NEVER)
    serviceA(){
     do sql 1
     1/0;
     do sql 2
    }
    上の例でserviceを呼び出した後、default AutoCommt=trueであれば、serviceB方法及びserviceAのsql 1は有効になります。
    7、PROPAAGATION_NESTEP
    説明:現在、事務があるなら、SavePoint技術を使って現在の事務状態を保存して、下の階に一つの接続を共有して、NESTED内部でエラーが発生した場合、自分でSavePointという状態に戻します。外部に異常が発生したら、外部の事務提出を継続して行うことができます。埋め込み業務の妨害を受けません。外部の事务に异常が出たら、大きな事务はロールバックします。
    注意:スプリングコンフィギュレーショントランザクションマネージャは、次のようにnetedTransation Allowed=trueをアクティブに指定します。
    
     <bean id="dataTransactionManager"
     class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataDataSource" />
      <property name="nestedTransactionAllowed" value="true" />
     </bean>
    小さな例を見て、コードは以下の通りです。
    
    @Transactional
    public void service(){
     serviceA();
     try{
      serviceB();
     }catch(Exception e){
     }
    }
    serviceA(){
     do sql
    }
    @Transactional(propagation=Propagation.NESTED)
    serviceB(){
     do sql1
     1/0;
     do sql2
    }
    serviceBは埋め込まれた業務で、内部に運行時の異常が投げられました。だから、serviceBは全部ロールバックされました。serviceが異常を捕まえたので、serviceAは正常に提出できます。
    もう一つの例を見ますと、コードは以下の通りです。
    
    @Transactional
    public void service(){
      serviceA();
      serviceB();
      1/0;
    }
    @Transactional(propagation=Propagation.NESTED)
    serviceA(){
     do sql
    }
    serviceB(){
     do sql
    }
    serviceに異常があるため、service全体の方法がロールバックされます。これはPROPAAGATIONということです。REQUIRES_NEWが違っているところで、NESTED方式のインサート業務は外部事務の異常を受けてロールバックします。)
    簡単な分析を実現する
    上記の例では、spring事務が提供するいくつかの伝播属性を説明しましたが、さまざまな業務ニーズを満たすために、業務に応じて決められます。次に,これらの伝搬特性を実現するためのspringの最も重要な技術的依存性は何かを見てきた。この小節はPROPAAGATIONを列挙する。REQUIRES_NEWとPropgations.NESTEDはそれぞれ簡単に説明します。
    1、PROPAAGATION_REQUIRES_NEW実現の原理
    以下のコードの呼び出し:
    
    @Transactional
    public void service(){
     serviceB();
     try{
      serviceA();
     }catch(Exception e){
     }
    }
    
    @Transactional(propagation=Propagation.REQUIRES_NEW)
    serviceA(){
     do sql 1
     1/0;
     do sql 2
    }
    serviceB(){
     do sql
    }
    実行原理図は以下の通りです。

    a.事務状態オブジェクトを作成し、新たな接続を取得し、接続のaut Comit、fetSize、timeoutなどの属性をリセットする。
    b.接続をThreadLocal変数に結び付ける
    c.現在の事務を保留し、現在の事務状態の対象、接続などの情報をSuspendedResourceオブジェクトにパッケージ化し、回復に用いることができます。
    d.新たなビジネス状態オブジェクトを作成し、新たな接続を取得し、新たに接続されたaut Comit、fetch Size、timeoutなどの属性をリセットし、同時にSuspendResourceオブジェクトを保存し、ビジネスの回復のために、新しい接続をThreadLocal変数(上書き操作)に結び付ける。
    e.異常を捕獲し、ThreadLocalへの接続を戻し、接続パラメータを回復し、接続をクローズし、SuspendedResourceを回復する。
    f.ThreadLocal変数における接続を提出し(serviceBが提出されたため)、接続パラメータを復元し、接続をオフにして、データソースを返します。
    したがって、プログラム実行の結果、serviceAはロールバックされ、serviceBは正常に提出されました。
    2、PROPAAGATION_NESTEP実現原理
    以下のコードの呼び出し:
    
    @Transactional
    public void service(){
     serviceA();
     try{
       serviceB();
     }catch(Exception e){
     }
    }
    serviceA(){
     do sql
    }
    @Transactional(propagation=Propagation.NESTED)
    serviceB(){
     do sql1
     1/0;
     do sql2
    }
    実行原理図は以下の通りです。

    a.事務状態オブジェクトを作成し、新たな接続を取得し、接続のaut Comit、fetSize、timeoutなどの属性をリセットする。
    b.接続をThreadLocal変数に結び付ける
    c.現在の事務状態オブジェクトを使用して、ThreadLocal接続先を取得し、現在接続されているSavePointを保存し、異常回復のために使用します。SavePointはserviceAを実行した後の状態です。
    d.異常を捕獲し、c中のSavePointを使って事務ロールバックを行い、つまりserviceAを実行した状態に状態をロールバックして、serviceBメソッドの実行は無効となります。
    e.ThreadLocalの接続先を取得し、事務を提出し、接続属性を回復し、接続をクローズする
    その他
    springは底のデータソースをもとに、ThreadLocal、SavePointなどの技術点を利用して、多様な事務伝播属性を実現し、複雑な業務を実現しやすいです。伝播特性の原理を理解してこそ、springトランザクションをより良く制御することができる。Springロールバックは異常な捕獲に依存しています。デフォルトでは、RuntimeExceptionとErrrorをスローするだけで、ロールバックすることができます。もちろん設定ができます。詳細は@Transactionのコメントを参照することができます。
    締め括りをつける
    springの声明式の事務は私達に極めて便利さを持ってきて、この利器をうまく使うために、底の原理を理解するのはやはり必要で、本編はspring事務の氷山の一角だけで、読者はこの基礎の上で自分で深く探求することができます。
    以上が本文のspring事務Propagationとその実現原理についての詳しい内容です。興味のある方は引き続き当駅の他のテーマを参照してください。友達のサポートに感謝します。