スプリング物事の属性(個人的にはよく書けていると思います)


Spring宣言トランザクションは、複雑なトランザクションから解放されます.接続の取得、接続のクローズ、トランザクションのコミット、ロールバックなどの操作を処理する必要がなくなります.トランザクションに関連するメソッドで大量のtry...catch...finallyコードを処理する必要はありません.Spring宣言トランザクションを使用する場合、トランザクション属性という非常に重要な概念があります.トランザクション・プロパティは、通常、トランザクションの伝播動作、トランザクションの独立性レベル、トランザクションのタイムアウト値、トランザクションの読取り専用フラグから構成されます.トランザクションの分割には、トランザクション定義、すなわちトランザクションのプロパティを構成する必要があります.SpringはTransactionDefinitionインタフェースでこれらのプロパティを定義し、PlatfromTransactionManagerで使用します.PlatfromTransactionManagerはspringトランザクション管理のコアインタフェースです.
TransactionDefinition
public interface TransactionDefinition {
    int getPropagationBehavior();
    int getIsolationLevel();
    int getTimeout();
    boolean isReadOnly();
}

gettimeout()メソッドは、トランザクションが何秒以内に完了しなければならないかを返します.isReadOnly()は、トランザクションが読み取り専用かどうか、トランザクションマネージャがこの戻り値に基づいて最適化し、トランザクションが読み取り専用であることを確認します.getisolationLevel()メソッドは、トランザクションの独立性レベルを返し、トランザクションマネージャは、別のトランザクションがこのトランザクション内のどのデータを表示できるかを制御します.TransactionDefinitionインタフェースには、5つの異なるトランザクション独立性レベルISO LATION_が定義されています.DEFAULTこれはPlatfromTransactionManagerのデフォルトの独立性レベルであり、データベースのデフォルトのトランザクション独立性レベルを使用します.また、JDBCの独立性レベルに対応する4つのISO LATION_READ_UNCOMMITTEDこれはトランザクションの最も低い独立性レベルであり、このトランザクションがコミットされていないデータを別のトランザクションで見ることができることを許可します.この独立性レベルでは、汚れた読み取り、重複しない読み取り、幻の読み取りが発生します. 例: Maryの元賃金は1000で、財務担当者はMaryの賃金を8000に変更したが、事務は提出しなかった.
Connection con1 = getConnection();
con.setAutoCommit(false);
update employee set salary = 8000 where empId ="Mary";

同時に、マリーは自分の給料を読んでいます.
Connection con2 = getConnection();
select  salary from employee where empId ="Mary";
con2.commit();

マリーは自分の給料が8000になったことに気づいて、喜んでいます!財務は操作が間違っていることに気づき、事務をロールバックし、Maryの給料は1000になった.
//con1
  con1.rollback();

このように、Maryが記録した給料8000は汚いデータです.ISOLATION_READ_COMMITTED  トランザクションが変更されたデータがコミットされた後、別のトランザクションによって読み込まれることを保証します.別のトランザクションでは、トランザクションがコミットされていないデータを読み取ることはできません.このトランザクション独立性レベルでは、汚れた読み取りは回避できますが、重複しない読み取りと幻の読み取りが発生する可能性があります.ISOLATION_REPEATABLE_READ  このトランザクション・独立性レベルは、汚れた読み取りを防止し、重複しないことができます.しかし、幻読みが現れる可能性があります.これにより、1つのトランザクションが別のトランザクションでコミットされていないデータを読み取ることができないことを保証するほか、次の状況の発生を回避することが保証されます(重複して読むことはできません).トランザクション1では、Maryは自分の給料が1000であることを読み取り、操作は完了しなかった.
con1 = getConnection();
select salary from employee empId ="Mary";

事務2では、財務担当者がMaryの給与を2000に変更し、事務を提出する.
con2 = getConnection();
update employee set salary = 2000;
con2.commit();

事務1でマリーが再び自分の給料を読み取ったとき、給料は2000になります
//con1
select salary from employee empId ="Mary";

1つのトランザクションで前後2回の読み取りの結果は発生せず、繰り返し不可能になります.使用ISO LATION_REPEATABLE_READはこのようなことを避けることができる.ISOLATION_SERIALIZABLEこれは、最もコストがかかりますが、最も信頼できるトランザクション・アイソレーション・レベルです.トランザクションは順次実行されます.汚れた読みを防止し、繰り返して読むことができないほか、幻の読みも避けられます.現在、給料が1000人の従業員は10人います.トランザクション1では、すべての給与が1000の従業員を読み取ります.
con1 = getConnection();
Select * from employee where salary =1000;

合計10件のレコードを読み込むと、別のトランザクションがemployeeテーブルに従業員レコードを挿入し、給与も1000件になります.
con2 = getConnection();
Insert into employee(empId,salary) values("Lili",1000);
con2.commit();

トランザクション1給与が1000のすべての従業員を再読み込み
//con1
select * from employee where salary =1000;

合計11件のレコードが読み込まれ、幻読みが発生した.ISOLATION_SERIALIZABLEはこのようなことを避けることができます.しかし、これも最大のリソースを費やしています.getPropagationBehavior()は、アクティブなトランザクションがあるかどうかによってトランザクション呼び出しを決定するトランザクションの伝播動作を返します.TransactionDefinitionインタフェースでは、7つのトランザクション伝播動作が定義されています.PROPAGATION_REQUIRDトランザクションが存在する場合は、現在のトランザクションがサポートされます.トランザクションがない場合は、新しいトランザクションが開きます.
//     PROPAGATION_REQUIRED
methodA{
……
methodB();
……
}
//     PROPAGATION_REQUIRED
methodB{
   ……
}

Spring宣言トランザクションを使用し、springはAOPを使用して宣言トランザクションをサポートします.トランザクションのプロパティに基づいて、メソッド呼び出しの前にトランザクションを開くかどうかを自動的に決定し、メソッドの実行後にトランザクションのコミットまたはロールバックを決定します.methodBメソッドを個別に呼び出す
main{
 metodB();
}
main{
  metodB();
}

に相当
Main{
Connection con=null;
   rry{
      con = getConnection();
      con.setAutoCommit(false);
//    
methodB();
//    
con.commit();
}
Catch(RuntimeException ex){
  //    
  con.rollback();
}
finally{
  //    
  closeCon();
}
}

Springは、methodBメソッド内のすべての呼び出しが同じ接続になることを保証します.methodBを呼び出すと、存在するトランザクションが1つもないので、新しい接続が得られ、新しいトランザクションが開きます.MethodAを単独で呼び出すと、MethodA内でMethodBが呼び出され、実行効果は
main{
   Connection con = null;
   try{
      con = getConnection();
      methodA();
      con.commit();
}
cathc(RuntimeException ex){
 con.rollback();
}
finally{
  closeCon();
}
}

MethodAを呼び出すと、環境にトランザクションがないため、新しいトランザクションが開きます.MethodAでMethoddBを呼び出すと、環境にトランザクションがすでに存在するため、methodBが現在のトランザクションに追加されます.PROPAGATION_SUPPORTSにトランザクションがある場合は、現在のトランザクションをサポートします.トランザクションがない場合は、トランザクションの実行ではありません.しかし、トランザクション同期のトランザクションマネージャについては、PROPAGATION_SUPPORTSは事務を使わないのとは少し違います.
//     PROPAGATION_REQUIRED
methodA(){
  methodB();
}
//     PROPAGATION_SUPPORTS
methodB(){
  ……
}

単純にmethodBを呼び出すと、methodBメソッドは非トランザクションで実行されます.methdAが呼び出されると、methodBはmethodAのトランザクションに追加され、トランザクションが実行されます.PROPAGATION_MANDATORYにトランザクションが既に存在する場合は、現在のトランザクションをサポートします.アクティブなトランザクションが1つもない場合は、例外が放出されます.
//     PROPAGATION_REQUIRED
methodA(){
  methodB();
}
//     PROPAGATION_MANDATORY
methodB(){
  ……
}

methodBを個別に呼び出すと、現在アクティブなトランザクションが1つもないため、異常throw new I l e g a l T r a n s c t ionStateException(「Transaction propagation'mandatory'but no existing transaction found」)が放出されます.methodAが呼び出されると、methodBはmethodAのトランザクションに追加され、トランザクションが実行されます.PROPAGATION_REQUIRES_NEWは常に新しいトランザクションを開きます.トランザクションがすでに存在する場合は、その存在するトランザクションを保留します.
//     PROPAGATION_REQUIRED
methodA(){
  doSomeThingA();
methodB();
doSomeThingB();
}
//     PROPAGATION_REQUIRES_NEW
methodB(){
  ……
}

methodBを単独で呼び出す場合、methodbをREQUIRDとして宣言することに相当します.新しいトランザクションを開き、トランザクションで実行します.methodAが呼び出されると
main(){
  methodA();
}

状況は大きく異なります.以下の効果に相当します.
main(){
 TransactionManager tm = null;
try{
  //    JTA     
   tm = getTransactionManager();
   tm.begin();//        
   Transaction ts1 = tm.getTransaction();
   doSomeThing();
   tm.suspend();//      
   try{
     tm.begin();//         
     Transaction ts2 = tm.getTransaction();
     methodB();
     ts2.commit();//       
                                            
   }
  Catch(RunTimeException ex){
     ts2.rollback();//       
  }
  finally{
    //    
  }
   //methodB    ,       
   tm.resume(ts1);
doSomeThingB();
   ts1.commit();//       
}
catch(RunTimeException ex){
  ts1.rollback();//       
}
finally{
  //    
}
}

ここで,ts 1を外層トランザクション,ts 2を内層トランザクションと呼ぶ.上記のコードから、ts 2とts 1は2つの独立したトランザクションであり、互いに関係がないことがわかります.Ts 2が成功するかどうかはts 1に依存しない.methodAメソッドがmethodBメソッドを呼び出した後のdoSomeThingBメソッドが失敗した場合、methodBメソッドの結果がコミットされます.methodB以外のコードによる結果はロールバックされた.PROPAGATION_を使うREQUIRES_NEWは、トランザクションマネージャとしてJtaTransactionManagerを使用する必要があります.PROPAGATION_NOT_SUPPORTED  常に非トランザクションで実行され、存在するトランザクションが保留されます.
//     PROPAGATION_REQUIRED
methodA(){
  doSomeThingA();
methodB();
doSomeThingB();
}
//     PROPAGATION_NOT_SUPPORTED
methodB(){
  ……
}

methodBが単独で呼び出されると、トランザクションメカニズムは有効になりません.非トランザクションで実行されます.methodAを呼び出すと、次の効果に相当します.
main(){
 TransactionManager tm = null;
try{
  //    JTA     
   tm = getTransactionManager();
   tm.begin();//        
   Transaction ts1 = tm.getTransaction();
   doSomeThing();
   tm.suspend();//      
     methodB();
   //methodB    ,       
   tm.resume(ts1);
doSomeThingB();
   ts1.commit();//       
}
catch(RunTimeException ex){
  ts1.rollback();//       
}
finally{
  //    
}
}

PROPAGATION_を使うNOT_SUPPORTEDは、JtaTransactionManagerをトランザクションマネージャとして使用する必要もあります.PROPAGATION_NEVERは常に非トランザクションで実行され、アクティブなトランザクションがある場合は例外を放出します.
//     PROPAGATION_REQUIRED
methodA(){
  doSomeThingA();
methodB();
doSomeThingB();
}
//     PROPAGATION_NEVER
methodB(){
  ……
}

methodBを単独で呼び出すと、トランザクションの実行ではありません.methodAを呼び出すと異常throw new I llegalTransactionStateException(「Transaction propagation'never'but existing transaction found」)が放出されます.PROPAGATION_NESTEDアクティブなトランザクションが存在する場合は、ネストされたトランザクションで実行されます.アクティブなトランザクションがない場合は、TransactionDefinition.PROPAGATION_REQUIRDプロパティ実行これはネストされたトランザクションで、JDBC 3.0ドライバを使用する場合、DataSourceTransactionManagerのみがトランザクションマネージャとしてサポートされます.JDBCドライバのjava.sql.Savepointクラスが必要です.いくつかのJTAのトランザクションマネージャ実装も同様の機能を提供している可能性があります.PROPAGATION_を使うNESTEDでは、PlatformTransactionManagerのnestedTransactionAllowedプロパティをtrueに設定する必要があります.一方、nestedTransactionAllowedプロパティの値はfalseにデフォルト設定されています.
//     PROPAGATION_REQUIRED
methodA(){
  doSomeThingA();
methodB();
doSomeThingB();
}
//     PROPAGATION_NESTED
methodB(){
  ……
}

methodBメソッドを個別に呼び出す場合は、REQUIREDプロパティに従って実行します.methodAメソッドを呼び出すと、次の効果に相当します.
main(){
Connection con = null;
Savepoint savepoint = null;
try{
  con = getConnection();
  con.setAutoCommit(false);
  doSomeThingA();
  savepoint = con2.setSavepoint();
  try
      methodB();
  }catch(RuntimeException ex){
     con.rollback(savepoint);
  }
  finally{
    //    
  }
  doSomeThingB();
  con.commit();
}
catch(RuntimeException ex){
  con.rollback();
}
finally{
  //    
}
}

methodBメソッドが呼び出される前にsetSavepointメソッドを呼び出し、現在のステータスをsavepointに保存します.methodBメソッドの呼び出しに失敗した場合は、以前に保存した状態に戻ります.ただし、この場合のトランザクションはコミットされず、後続のコード(doSomeThingB()メソッド)呼び出しに失敗した場合、methodBメソッドを含むすべての操作がロールバックされることに注意してください.ネストされたトランザクションの重要な概念は、内層トランザクションが外層トランザクションに依存することです.外層トランザクションが失敗すると、内層トランザクションのアクションがロールバックされます.内層トランザクションの操作に失敗しても、外層トランザクションのロールバックは発生しません.PROPAGATION_NESTEDとPROPAGATION_REQUIRES_NEWの違い:ネストされたトランザクションのように非常に似ています.アクティブなトランザクションが存在しない場合は、新しいトランザクションが開きます.PROPAGATION_を使うREQUIRES_NEWの場合、内層トランザクションと外層トランザクションは2つの独立したトランザクションのように、内層トランザクションがコミットされると、外層トランザクションはロールバックできません.2つのトランザクションは互いに影響しない.2つのトランザクションは、真のネストされたトランザクションではありません.同時にJTAトランザクションマネージャのサポートが必要です.PROPAGATION_を使うNESTEDでは、外部トランザクションのロールバックにより、内部トランザクションのロールバックが発生します.内層トランザクションの例外は、外層トランザクションのロールバックを招くことはありません.これは真のネストされたトランザクションです.DataSourceTransactionManager savepointを使用してPROPAGATION_をサポートNESTEDでは、JDBC 3.0以上のドライバおよび1.4以上のJDKバージョンのサポートが必要です.他のJTA TransactionManagerの実装では、サポート方法が異なる場合があります.PROPAGATION_REQUIRDは私たちの最初のトランザクション伝播行為であるべきです.ほとんどのトランザクション要件を満たすことができます.
原文住所:http://www.iteye.com/topic/78674