posts - 66,  comments - 11,  trackbacks - 0

              在軟件中,要么全有要么全無(wú)的操作成為事務(wù)。事務(wù)允許你把幾個(gè)操作組成一個(gè)單一的工作單元,這個(gè)工作單元要么全部發(fā)生要么全部不發(fā)生。如果每件事都順利,那么這個(gè)事務(wù)是成功的。但是如果任何一件事情出錯(cuò)的話,那么已經(jīng)發(fā)生的行為就被清除掉,就像什么事情都沒(méi)發(fā)生一樣。
              Spring對(duì)事務(wù)管理有豐富的支持,程序控制的和聲明式的。
              原子性(Atomic):事務(wù)由一個(gè)或多個(gè)行為綁定在一起組成,好像是一個(gè)單獨(dú)工作單元。原子性確保在十五中的所有操作要么都發(fā)生,要么都不發(fā)生。
              一致性(Consistent):一旦一個(gè)事務(wù)結(jié)束了(不管成功失敗),系統(tǒng)所處的狀態(tài)和它的業(yè)務(wù)規(guī)則是一致的。就是說(shuō)數(shù)據(jù)應(yīng)當(dāng)不會(huì)被破壞。
              隔離性(Isolated):事務(wù)應(yīng)該允許多個(gè)用戶操作同一數(shù)據(jù),一個(gè)用戶的操作不會(huì)和其他用戶的操作相混淆。因此,事務(wù)必須是互相隔離的,防止并發(fā)讀寫同一數(shù)據(jù)的情況發(fā)生。
              持久性(Durable):一旦事務(wù)完成,事務(wù)的結(jié)果應(yīng)該持久化,這樣不管什么樣的系統(tǒng)崩潰,他們都將幸免于難。
           
              Spring對(duì)程序控制事務(wù)管理的支持和EJB的有很大不同。EJB的事務(wù)管理和JTA密不可分,和EJB不同的是,Spring使用了一種回調(diào)機(jī)制,把真實(shí)的事務(wù)實(shí)現(xiàn)從事務(wù)代碼中抽象出來(lái)。選擇程序控制事務(wù)管理還是聲明式事務(wù)管理,很大程度上是在細(xì)粒度控制與簡(jiǎn)便操作之間做出決定。當(dāng)你在代碼中編寫事務(wù)時(shí),你能精確控制事務(wù)的邊界,在你希望的地方精確的開始和結(jié)束。典型的情況下,你不需要程序控制事務(wù)所提供的細(xì)粒度控制,你會(huì)選擇在上下文定義文件中聲明你的事務(wù)。

              Spring對(duì)聲明式事務(wù)管理的支持是通過(guò)它的AOP框架實(shí)現(xiàn)的。這樣做是非常自然的,因?yàn)槭聞?wù)是系統(tǒng)級(jí)的,凌駕于應(yīng)用的主要功能之上的。

              在Spring里,事務(wù)屬性是對(duì)事務(wù)策略如何應(yīng)用到方法的描述。這個(gè)描述包括:傳播行為、隔離級(jí)別、只讀提示、事務(wù)超時(shí)間隔
              傳播行為:
              PROPAGATION_MANDATORY:表示該方法必須運(yùn)行在一個(gè)事務(wù)中。如果當(dāng)前事務(wù)不存在,將拋出一個(gè)異常。
              PROPAGATION_NESTED:表示如果當(dāng)前已經(jīng)存在一個(gè)事務(wù),則該方法應(yīng)當(dāng)運(yùn)行在一個(gè)嵌套的事務(wù)中。被嵌套的事務(wù)可以從當(dāng)前事務(wù)中單獨(dú)的提交或回滾。如果當(dāng)前事務(wù)不存在,那么它看起來(lái)和PROPAGATION_REQUIRED沒(méi)有兩樣。
              PROPAGATION_NEVER:表示當(dāng)前的方法不應(yīng)該運(yùn)行在一個(gè)事務(wù)上下文中。如果當(dāng)前存在一個(gè)事務(wù),則會(huì)拋出一個(gè)異常。
              PROPAGATION_NOT_SUPPORTED:表示該方法不應(yīng)在事務(wù)中運(yùn)行。如果一個(gè)現(xiàn)有的事務(wù)正在運(yùn)行中,它將在該方法的運(yùn)行期間被掛起。
              PROPAGATION_REQUIRED:表示當(dāng)前方法必須運(yùn)行在一個(gè)事務(wù)中。如果一個(gè)現(xiàn)有的事務(wù)正在運(yùn)行中,該方法將運(yùn)行在這個(gè)事務(wù)中。否則的話,要開始一個(gè)新的事務(wù)。
              PROPAGATION_REQUIRES_NEW:表示當(dāng)前方法必須運(yùn)行在它自己的事務(wù)里。它將啟動(dòng)一個(gè)新的事務(wù)。如果有事務(wù)運(yùn)行的話,將在這個(gè)方法運(yùn)行期間被掛起。
              PROPAGATION_SUPPORTS:表示當(dāng)前方法不需要事務(wù)處理環(huán)境,但如果有一個(gè)事務(wù)已經(jīng)在運(yùn)行的話,這個(gè)方法也可以在這個(gè)事務(wù)里運(yùn)行。

             傳播規(guī)則回答了一個(gè)問(wèn)題:就是新的事務(wù)是否要被啟動(dòng)或是被掛起,或者方法是否要在事務(wù)環(huán)境中運(yùn)行。

             隔離級(jí)別:在一個(gè)典型的應(yīng)用中,多個(gè)事務(wù)并發(fā)運(yùn)行,經(jīng)常會(huì)操作同一個(gè)數(shù)據(jù)來(lái)完成它們的任務(wù)。并發(fā),雖然是必須的,但會(huì)導(dǎo)致下面問(wèn)題:
          1、臟讀:臟讀發(fā)生在一個(gè)事務(wù)讀取了被另一個(gè)事務(wù)改寫但還未提交的數(shù)據(jù)時(shí)。如果這些改變?cè)谏院蟊换貪L,那么第一個(gè)事務(wù)讀取的數(shù)據(jù)就是無(wú)效的。
          2、不可重復(fù)讀:不可重復(fù)讀發(fā)生在一個(gè)事務(wù)執(zhí)行相同的查詢2次或2次以上,但每一次查詢結(jié)果都不同時(shí)。這通常是由于另一個(gè)并發(fā)事務(wù)在2次查詢之間更新了數(shù)據(jù)。
          3、幻讀:幻讀和不可重復(fù)讀相似。當(dāng)一個(gè)事務(wù)讀取幾行紀(jì)錄后,另一個(gè)并發(fā)事務(wù)插入一些記錄,幻讀就發(fā)生了。隔離級(jí)別有如下幾個(gè):
          ISOLATION_DEFAULT:使用后端數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別
          ISOLATION_READ_UNCOMMITTED:允許你讀取還未提交的改變了的數(shù)據(jù),可能導(dǎo)致臟讀、幻讀、不可重復(fù)讀
          ISOLATION_READ_COMMITTED:允許在并發(fā)事務(wù)已經(jīng)提交后讀取。可防止臟讀,但幻讀和不可重復(fù)讀仍可能發(fā)生。
          ISOLATION_REPEATABLE_READ:對(duì)相同字段的多次讀取的結(jié)果是一致的,除非數(shù)據(jù)被事務(wù)本身改變。可防止臟讀和不可重復(fù)讀,但幻讀仍可能發(fā)生。
          ISOLATION_SERIALIZABLE:完全服從ACID的隔離級(jí)別,確保不發(fā)生臟讀、不可重復(fù)讀和幻讀。這在所有隔離級(jí)別中也是最慢的。

              只讀:如果一個(gè)事務(wù)只對(duì)后端是據(jù)庫(kù)執(zhí)行讀操作,數(shù)據(jù)庫(kù)就可能利用事務(wù)只讀的特性,使用某些優(yōu)化措施。通過(guò)聲明一個(gè)事務(wù)為只讀,你就給了后端數(shù)據(jù)庫(kù)一個(gè)機(jī)會(huì),來(lái)應(yīng)用那些它認(rèn)為合適的優(yōu)化措施。因?yàn)橹蛔x的優(yōu)化措施是在事務(wù)啟動(dòng)時(shí)由后端數(shù)據(jù)庫(kù)實(shí)施的,所以,只有將那些具有可能啟動(dòng)新事務(wù)的傳播行為的方法的事務(wù)標(biāo)記成只讀才有意義(PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED) TransactionProxyFactoryBean參照一個(gè)方法的事務(wù)屬性,決定如何在那個(gè)方法上執(zhí)行事務(wù)策略。

          <?xml version="1.0" encoding="UTF-8"?>
          <beans
              
          xmlns="http://www.springframework.org/schema/beans"
              xmlns:xsi
          ="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation
          ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
              
          <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
                  
          <property name="jndiName">
                      
          <value>java:comp/env/jdbc/myDatasource</value>
                  
          </property>
              
          </bean>
              
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                  
          <property name="dataSource">
                      
          <ref bean="dataSource"/>
                  
          </property>
              
          </bean>
              
          <!-- 這個(gè)對(duì)象有一個(gè)值為courseService的id.當(dāng)應(yīng)用從應(yīng)用上下文里請(qǐng)求一個(gè)courseService時(shí),它將得到一個(gè)被
              TransactionProxyFactoryBean包裹的實(shí)例。 
          -->
              
          <bean id="courseService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                  
          <!-- 代理所實(shí)現(xiàn)的接口 -->
                  
          <property name="proxyInterfaces">
                      
          <list>
                          
          <value>
                              com.springinaction.training.service.CourseService
                          
          </value>
                      
          </list>
                  
          </property>
                  
          <!-- 被代理的對(duì)象 -->
                  
          <property name="target">
                      
          <ref bean="courseServiceTarget"/>
                  
          </property>
                  
          <!-- 事務(wù)管理器 -->
                  
          <property name="transactionManager">
                      
          <ref bean="transactionManager"/>
                  
          </property>
                  
          <!-- 事務(wù)的屬性源 -->
                  
          <property name="transactionAttributeSource">
                      
          <ref bean="transactionAttributeSource"/>
                  
          </property>
              
          </bean>
              
          <!-- 要知道盡管可以改變MatchAlwaysTransactionAttributeSource的事務(wù)屬性參數(shù),但它總是返回相同的事務(wù)屬性,而
              不關(guān)心參與交易的哪一個(gè)方法。當(dāng)你有一個(gè)相對(duì)簡(jiǎn)單的應(yīng)用,把同樣的事務(wù)策略應(yīng)用到所有方法都沒(méi)問(wèn)題時(shí),使用MatchAlwaysT
              ransactionAttributeSource就相當(dāng)好。但是,在那些更為復(fù)雜的應(yīng)用中,你很可能需要對(duì)不同的方法應(yīng)用不同的事務(wù)策略。在那樣
              情況下,你需要在應(yīng)用何種策略的問(wèn)題上做更多精確的控制。 
          -->
              
          <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource">
                  
          <property name="transactionAttribute">
                      
          <ref bean="myTransactionAttribute"/>
                  
          </property>
              
          </bean>
              
          <!-- 定義事務(wù)策略 -->
              
          <bean id="myTransactionAttribute" class="org.springframework.transaction.interceptor.DefaultTransactionAttribute">
                  
          <!-- 傳播行為 -->
                  
          <property name="propagationBehaviorName">
                      
          <value>PROPAGATION_REQUIRES_NEW</value>
                  
          </property>
                  
          <!-- 隔離級(jí)別 -->
                  
          <property name="isolationLevelName">
                      
          <value>ISOLATION_REPEATABLE_READ</value>
                  
          </property>
              
          </bean>
          </beans>

           

          除了將transactionAttributeSource對(duì)象織入到TransactionProxyFactoryBean的transactionAttributeSource屬性中外,還有一種簡(jiǎn)單的方法。發(fā)展到現(xiàn)在,TransactionProxyFactoryBean也有一個(gè)transactionAttributes屬性為transactionProperties.

          <?xml version="1.0" encoding="UTF-8"?>
          <beans
              
          xmlns="http://www.springframework.org/schema/beans"
              xmlns:xsi
          ="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation
          ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
              
          <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
                  
          <property name="jndiName">
                      
          <value>java:comp/env/jdbc/myDatasource</value>
                  
          </property>
              
          </bean>
              
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                  
          <property name="dataSource">
                      
          <ref bean="dataSource"/>
                  
          </property>
              
          </bean>
              
          <!-- 這個(gè)對(duì)象有一個(gè)值為courseService的id.當(dāng)應(yīng)用從應(yīng)用上下文里請(qǐng)求一個(gè)courseService時(shí),它將得到一個(gè)被
              TransactionProxyFactoryBean包裹的實(shí)例。 
          -->
              
          <bean id="courseService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
                  
          <!-- 代理所實(shí)現(xiàn)的接口 -->
                  
          <property name="proxyInterfaces">
                      
          <list>
                          
          <value>
                              com.springinaction.training.service.CourseService
                          
          </value>
                      
          </list>
                  
          </property>
                  
          <!-- 被代理的對(duì)象 -->
                  
          <property name="target">
                      
          <ref bean="courseServiceTarget"/>
                  
          </property>
                  
          <!-- 事務(wù)管理器 -->
                  
          <property name="transactionManager">
                      
          <ref bean="transactionManager"/>
                  
          </property>
                  
          <!-- 事務(wù)的屬性源 -->
                  
          <property name="transactionAttributeSource">
                      
          <ref bean="transactionAttributeSource"/>
                  
          </property>
              
          </bean>
              
          <!-- NameMatchTransactionAttributeSource的properties屬性把方法名映射到事務(wù)屬性描述器上。注意CourseException
              用一個(gè)負(fù)號(hào)標(biāo)記。異常可以用負(fù)號(hào)或正號(hào)標(biāo)記,當(dāng)負(fù)號(hào)異常拋出時(shí),將觸發(fā)回滾;相反的,正號(hào)異常表示事務(wù)仍可提交,即使這個(gè)異常拋出 
          -->
              
          <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
                  
          <property name="properties">
                      
          <props>
                          
          <prop key="enrollStudentInCourse">
                              PROPAGATION_REQUIRES_NEW,ISOLATION_REPEATABLE_READ,readOnly,
                              -CourseException
                          
          </prop>
                          
          <!-- 還可以使用通配符 -->
                          
          <prop key="get*">
                              PROPAGATION_SUPPORTS
                          
          </prop>
                      
          </props>
                  
          </property>
              
          </bean>
          </beans>

           

           

          posted on 2009-11-22 11:43 王永慶 閱讀(261) 評(píng)論(0)  編輯  收藏 所屬分類: SPRING
          <2009年11月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          關(guān)注blogs

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 阜城县| 新和县| 津南区| 济宁市| 勃利县| 潼关县| 吴桥县| 辽阳县| 龙岩市| 南京市| 五莲县| 定襄县| 汽车| 阆中市| 滕州市| 石景山区| 兰西县| 定襄县| 云龙县| 贡山| 常州市| 商洛市| 南昌市| 左贡县| 大连市| 常德市| 赫章县| 固安县| 淮安市| 灌南县| 大余县| 邹平县| 长顺县| 临夏市| 宁德市| 寻甸| 府谷县| 宜宾市| 临桂县| 洛宁县| 桓台县|