Spring声明式事務管理及び事務ネスト


Spring声明式事務管理及び事務ネスト:Spring動的代理の一つの重要な特徴は、インターフェースに対するものであり、したがって、我々のdaoは動的エージェントを通してspringに事務を引き継ぐために、daoの前にインターフェースを抽象化しなければならない.もちろん、このような接続がなければ、springはCGLOBを使用して問題を解決する.
トランザクションの設定
Spring動的エージェントの重要な特徴は、インターフェースに対するものです.だから、私たちのdaoは動的エージェントを通してspringに事務を引き継ぐために、daoの前にインターフェースを抽象化しなければなりません.もちろん、このようなインターフェースがなければ、springはCGLOIBを使って問題を解決します.
一般的に、Springフレームを使用する場合、そのappicationContactext.xmlファイルで、hibernateトランザクションの使用を宣言することができる.
 <bean id=”tranManager”  class=”org.springframework.orm.hibernate3.HibernateTransactionManager”> 
 <property name=”sessionFactory”> 
 <ref bean=”SessionFactoryID” /> 
 </property> 
 </bean> 
 <bean id=”transactionInterceptor” 
 class=”org.springframework.transaction.interceptor.TransactionInterceptor”> 
 <property name=”transactionManager”> 
 <ref bean=”tranManager” /> 
 </property> 
 <property name=”transactionAttributes”> 
 <props> 
 <prop key=”*”>PROPAGATION_REQUIRED</prop> 
 </props> 
 </property> 
 </bean> 
 <bean id=”proxyCreator” 
 class=”org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator”> 
 <property name=”interceptorNames”> 
 <list> 
 <value>transactionInterceptor</value> 
 </list> 
 </property> 
 <property name=”beanNames”> 
 <list> 
 <value>*Biz</value> 
 </list> 
 </property> 
 </bean> 
上記の構成は、Biz拡張子のすべてのインターフェースクラスにおいて宣言された方法に対して事務的に構成されており、その事務の伝播戦略は、
  • PROPAAGATION_REQUIREDは、springで六つの事務伝播属性を定義しています.
  • PROPAAGATION_REQUIRED--現在の事務をサポートしています.もし現在事務がないなら、新しい事務を作ります.これは一番よくある選択です.
  • PROPAAGATION_SUPPORTS--現在の事務をサポートしておりますが、現在は事務がない場合は非事務で行います.
  • PROPAAGATION_MANDATORY--現在の事務をサポートしています.
  • PROPAAGATION_REQUIRES_NEW-新規事務は、現在の事務があれば、現在の事務を保留します.
  • PROPAAGATION_NOT_SUPPORTED--非事務的に操作を行い、現在の事務があれば、現在の事務を保留します.
  • PROPAAGATION_NEVER--非事務的に行われていますが、現在事務がある場合は異常を投げます.
  • PROPAAGATION_NESTEP-現在のトランザクションが存在する場合は、ネストトランザクション内で実行します.現在、事務がない場合は、PROPAAGATION_を行います.REQUIREDと同様の動作.
  • 最初の6つの戦略はEJB CMTと類似しています.7番目の(PROPAAGATIONUNESTER)はSpringによって提供される特殊変数です.
    これは、トランザクションマネージャまたはJDBC 3.0 Savepoint APIを使用して、SpringのDataSourceTransation Managerのような一連のトランザクション行動を提供する必要があります.
    トランザクションネスト
    私が見た誤解の中で、一番多いのは次のようなものです.
    参照
    二つの業務インターフェースServiceAとServiceBがあるなら、ServiceAの中に次のような方法があります.
     /** 
     *         PROPAGATION_REQUIRED 
     */ 
     void methodA() { 
     //    ServiceB     
     ServiceB.methodB(); 
     }
    もしServiceBのmethodBに事務が配置されたら、PROPAAGATION_に配置しなければなりません.NESTEP
    このような考えは多くの人を害しているかもしれません.Serviceの間ではお互いの呼び出しを避けるべきだと思っていますが、そのことを心配する必要はありません.PROPAAGATION.REQUIREDはよく分かりました.
    現在スレッドに既に事務が存在している場合、メソッド呼び出しはこのトランザクションに参加します.現在はトランザクションがない場合は、新しいトランザクションを作成します.したがって、ServiceB((zhi methodB)()のトランザクションは最も一般的なルールに従ってPROPAAGATION()に設定します.REQUIREDでもいいです.ServiceB(私たちは内部事務と言っています.以下の基礎を作るために)に異常が発生したら、ServiceA(Cute methodA)はこの異常を特殊に設定していない場合、事務提出(すなわち、MyCheckedExceptionの使い方)してください.どのようなServiceがDaoのような言論を調整することしかできないのか、springは事務属性の方法のブロックしか配置していません.どうやってあなたのこの方法がServiceですか?それともDaoですか?
    つまり、一番紛らわしいのはPROPAAGATIONです.REQUIRES_NEWとPROPAAGATION_NESTEPでは、この2つの方法の違いは何ですか?Jergen Hoellerの話を簡単に訳します.
    PROPAAGATION_REQUIRES_NEWは、環境に依存しない新しい「内部」の事務を開始します.この事務は完全にcomitedまたはrolled backによって外部の事務に依存せず、自分の隔離範囲、自分のロックなどを持っています.内部事務が開始されると、外部の事務は保留されます.
    一方、PROPAAGATION_NESTEPは「ネストされた」トランザクションを開始します.これは既に存在している本格的なサブトランザクションです.隠しトランザクションが開始されると、それはsavepointを取得します.このネストされたトランザクションが失敗したら、このsavepointにロールバックします.ネストトランザクションは外部事務の一部です.外部事務が終了してから提出されます.
    このことから、PROPAAGATION_REQUIRES_NEWとPROPAAGATION_NESTEPの最大の違いは、PROPAAGATION_REQUIRES_NEWはまったく新しい事务です.PROPAAGATION_NESTEPは外部事務のサブ事務であり、外部事務のcomitであれば、隠し事もcomitされ、このルールはroll backにも適用されます.
    外部事務は、ネストされた業務のsavepoint特性をどのように利用しますか?コードで話します.
     ServiceA { 
     
     /** 
     *         PROPAGATION_REQUIRED 
     */ 
     void methodA() { 
     ServiceB.methodB(); 
     } 
     
    } 
    
     ServiceB { 
     
     /** 
     *         PROPAGATION_REQUIRES_NEW 
     */ 
    . void methodB() { 
     }  
     }
    
    この場合、ServiceB铅methodBの事務属性はPROPAAGATION_である.REQUIRES_NEWは、したがって、両者は何の関係もありません.ServiceAとServiceBは、相手の実施状況によって事務の結果に影響を及ぼさないと思います.それらはもともと二つの事務です.ServiceBでServiceA隺methodAの事務を実行するときに、すでに保留されています.(事務に関する内容はすでに本文の討論範囲を超えています.時間があれば、また掛けた文章を書きます.)
    では、PROPAAGATIONKUNESTERはどうなっていますか?コードを見続けます.
    ServiceA { 
     
     /** 
     *         PROPAGATION_REQUIRED 
     */ 
     void methodA() { 
     ServiceB.methodB(); 
     } 
     } 
     ServiceB { 
     
     /** 
     *         PROPAGATION_NESTED 
     */ 
     void methodB() { 
    1 } 
    }
    1.ServiceA{2.3./*4.*事務属性はPROPAAGATION_UIQUID 5.*/6.void methodA(){7.ServiceB.methodB();8.↔9.10.}11.ServiceB{13.14.*15.事務属性はATOSTION.().OID{18.OPTION.OPTION.OND
    このような方法はネストされたトランザクションの最も価値のあるところであり、分岐実行の効果を発揮します.ServiceB.methodBが失敗した場合、ServiceC.methodC()を実行しますが、ServiceB.methodBはすでにそれが実行される前のSavePointにロールバックしていますので、汚いデータは発生しません.このような特性はいくつかの特殊な業務に使えますが、PROPAAGATIONUIQUIDとPROPAAGATIONUIQUIRESUNEWはこのようなことができません.
    2.コードが何も修正されていない場合、内部事務(すなわちServiceB rollback)は、まずServiceB.methodBがその実行前のSavePointにロールバックします.
    外部事務(つまりServiceA芫methodA)は、具体的な構成によって、自分がcomitなのか、それともrollbackなのかを決定します.
    上では、ネストトランザクションの使用シーンを大まかに説明しましたが、どのようにspringでPROPAAGATION_NESTEPを使うかを見てみます.まず、AbstractPlatform Transation Managerを見てみます.
    /** 
     * Create a TransactionStatus for an existing transaction. 
     */ 
     private TransactionStatus handleExistingTransaction( 
     TransactionDefinition definition, Object transaction, boolean debugEnabled) 
     throws TransactionException { 
     
     ...    
    
     if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { 
     if (!isNestedTransactionAllowed()) { 
     throw new NestedTransactionNotSupportedException( 
     ”Transaction manager does not allow nested transactions by default - ” + 
     ”specify 'nestedTransactionAllowed' property with value 'true'”); 
     } 
     if (debugEnabled) { 
     logger.debug(”Creating nested transaction with name [” + definition.getName() + ”]”); 
     } 
    if (useSavepointForNestedTransaction()) { 
     // Create savepoint within existing Spring-managed transaction, 
     // through the SavepointManager API implemented by TransactionStatus. 
     // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization. 
     DefaultTransactionStatus status = 
     newTransactionStatus(definition, transaction, false, false, debugEnabled, null);
     status.createAndHoldSavepoint(); 
     return status; 
     } 
     else { 
     // Nested transaction through nested begin and commit/rollback calls. 
     // Usually only for JTA: Spring synchronization might get activated here 
    . // in case of a pre-existing JTA transaction. 
     doBegin(transaction, definition); 
     boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER); 
    34. 34. return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null); 
    }
    }
    }
    一目瞭然
    1.transactionManagerのnetedTransation Allowed属性はtrueです.この属性はデフォルトでfalseです.
    Abstract Transactionation Storts((zhi createAndHold Savepoint)を見てください.
    /** 
     * Create a savepoint and hold it for the transaction. 
     * @throws org.springframework.transaction.NestedTransactionNotSupportedException 
     * if the underlying transaction does not support savepoints 
     */ 
     public void createAndHoldSavepoint() throws TransactionException { 
     setSavepoint(getSavepointManager().createSavepoint()); 
     }
    SavepointはSavepointManager.reat Savepointが実現したものと見られ、SavepointManagerの階層構造を見てみると、
    そのTemplateはJdbcTransation Object Supportであり、よく使われるDatasourceTransact Manager、Hibernation TransactionagerのTransactonObjectはすべてそのサブクラスである:
    JdbcTransation Object Supportは、私たちが二つの条件を満たすべきだと教えてくれました.
    2.java.sql.Savepointは必ず存在しています.つまり、jdkバージョンは1.4+を必要とします.
    3.Connection.get MetaData().supports Savepoints()はtrueである必要があります.jdbc driveはJDBC 3.0をサポートしなければなりません.
    これらの条件を満たしたら、PROPAAGATIONを使ってみてください.