Sping學習——事務

事務簡介

事務的出現是爲了保證數據的完整性和一致性,爲了防止意外的中斷致使數據出現錯誤.spring

事務三大接口

  1. PlatformTransactionManager 事務管理器.
    1.DataSourceTransactionManager:只能處理一個數據源,經過JDBC進行CRUD處理.
    2.JtaTransactionManager: JTA進行事務管理.
    3.HibernateTransactionManager:Hibernate框架操做數據庫.
  2. TransactionDefinition 保存了事務基礎信息,例如事物的傳播屬性、隔離級別等.
  3. TransactionStatus 保存了事務狀態信息,該事物是不是一個新的事務,是否提交是否須要回滾等.

事務四大特性

  1. 原子性:簡單來講就是事物的操做都是不可再分的,事務要麼一塊兒執行,要麼一塊兒都不執行.
  2. 一致性:事務執行後,執行先後的數據都必須是正確的,否則就要採起rollback(回滾)操做.
  3. 隔離性:多個事務一塊兒併發執行時,應該始終保持互相隔離,例如兩個事物同時修改一個數據時,只有其中一個事務進行commit修改數據成功後,另外一個事務纔開始修改.
  4. 持久性:事務修改數據一旦成功,這個數據應該是永久保存的不受其餘錯誤影響.

Spring中的事物管理

在Spring中事務的主要使用方式有兩種,一種是編程式事務管理另外一種是聲明式事務管理.編程式事務使用的是JDBC的原生API須要編寫大量代碼太過麻煩。所以如今Spring主要使用的是聲明式事務編程,Spring中的聲明式事務編程是基於AOP模式的,也就是在@before以前建立一個事物,@AfterRetuning以前確認一下事務是否須要回滾.聲明式事務的最大優勢就是不用寫一堆代碼而能夠直接經過註解(基於@Transaction註解)和配置文件(基於tx和aop命名空間)完成事務管理.數據庫

事務使用

@Transaction註解式

XML文件express

<!--引入事務管理器-->
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <property name="dataSource" ref="pooledDataSource"></property>
     </bean>
      <!--依賴tx名稱空間,開啓事務註解-->
     <tx:annotation-driven transaction-manager="transactionManager"/>

@Transaction註解主要是添加在Service組件的方法下編程

@Transactional(propagation=Propagation.REQUIRES,isolation=READ_COMMITTED)
    public void updateBook(String name,int price){
        libaryDao.updateBook(name, price);
    }

XML配置模式

<!--引入事務管理器-->
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <property name="dataSource" ref="pooledDataSource"></property>
     </bean>
    
     <aop:config>
        <!-- 配置事務切入點,哪些類哪些方法須要切入事務-->
         <aop:pointcut expression="execution(* com.libary.service*.*.*(..))" id="Point"/>
         <aop:advisor advice-ref="MyTx" pointcut-ref="Point"/>
     </aop:config>
     <!--  配置事務管理器 -->
     transaction-manager="transactionManager":
     <tx:advice id="MyTx" transaction-manager="transactionManager">
             <!--事務的屬性  -->
             <tx:attributes>
                <!--tx:method 指定了哪些方法須要加事務 -->
                 <tx:method name="*"/>
                 <tx:method name="update" propagation="REQUIRED" timeout="-1"/>
                 <tx:method name="query*" read-only="true"/>
             </tx:attributes>
     </tx:advice>

與Aop的使用相同,事務使用的思想應該是,重要的事務使用xml配置,不重要的事務使用@Transaction.併發

事務屬性

noRollbackFor:指定異常事務不回滾.
rollbackFor:指定異常事務回滾(編譯時錯誤原本不回滾使其回滾,編譯時錯誤默認是不回滾的除非使用try catch捕捉錯誤,可是運行錯誤是必定進行回滾)
timeout:事務超出指定時間即回滾,防止事務佔用資源.
readOnly:只能夠添加在查詢事務上,能夠優化事務的查詢速度.
isolation:隔離級別下面重點提到.
propagation:傳播行爲下面重點提到.
多種事務嵌套運行時,下面的事務服從頂層事務的屬性.框架

事務傳播行爲

傳播行爲的做用

事物的傳播行爲主要是爲了處理當有多個事務嵌套執行時,其中某個事務出現了錯誤,有哪些事務須要進行回滾.
如如下狀況優化

TestTx()
{
    A事務(REQUIRED)
    {
        B事務(REQUIRED_NEW)
        {
            C事務(REQUIRED)
            {
            }
        }
        D事務(REQUIRED)
        {
            E事務(REQUIRED)
            {
            }
        }
        F事務(REQUIRED_NEW)
    }     
}

傳播行爲

image

注意

平常事務管理中主要特別注意的事務是REQUIRED和REQUIRED_NEW
REQUIRED。
REQUIRED:REQUIRED的意思是與他的上層事務同生共死,你們共用一個事物。即如上代碼,若是D出現錯誤了A也出現錯誤,你們一塊兒進行rollback。
REQUIRED_NEW:REQUIRED_NEW的意思是我本身玩我本身的,我本身有一個事物,例如F出現錯誤了,與A事務有太多關係。F進行rollback,A不rollback。
特殊狀況:如上代碼,若是D出現錯誤了,那麼即使F是REQUIRED_NEW也不會執行,由於到D已經就直接拋出錯誤了。
重要的一點:
1.無論哪裏出錯,已經執行完的REQUIRED_NEW都不會出錯。
2.嵌套事務中由最頂層事務來決定Timeout等屬性。spa

事物的隔離級別

事務併發會出現的問題:

  1. 髒讀:事務A修改數據事務B讀取數據,事務A進行數據修改後還未正式提交,事務B已經讀取數據。可是事務A將數據rollback了.則事務B讀出了假數據.髒讀通常是絕對不可容許的.
例:x=10;
   A事務修改x=5但還未commit;
   B讀出x=5;
   A進行rollback,x=10;
   B讀出的x=5是假數據
  1. 不可重複讀:事務B讀取了數據,事務A修改了數據並無rollback,事務B再讀取數據,第一次讀取數據不一樣.
例:x=10;
   B事務讀取x=10;
   A事務修改x=5並commit;
   B再次讀取x=5,兩次讀取x不一樣;
  1. 幻讀:事務B讀取數據,事務A添加了數據,事務B再次讀取發現數據多了不少出來.
例:x=10;
   B事務讀取x=10;
   A事務添加y=20,i=30;
   B再次讀取讀出x=10,,y=20,i=30.多出大量數據。

隔離級別

使用@Transaction的isolation=Propagation.?屬性設置隔離級別.代理

例:@Transactional(propagation=Propagation.REQUIRES_NEW,isolation=READ_COMMITTED)

READ_UNCOMMITTED(讀未提交):容許髒讀、不可重讀讀、幻讀.
READ_COMMITTED(讀已提交):容許不可重讀和幻讀,不容許髒讀.
REPEATABLE READ(可重複讀):容許幻讀,不容許髒讀和不可重複讀.
SERIALIZABLE(串行化):不容許髒讀、不可重複讀、幻讀.code

特別注意

最後特別要注意的是千萬不要在某個Service組件中調用Service的事務方法(即不要調用本類方法),要記住Spring中的事物使用是基於AOP的,因此事務須要用代理對象,而直接在本類中調用的方法是沒法進行事務的。本類方法的嵌套無論調用多少個都是單個事務.

例:
@Service
public class LibaryService{
    @Autowired
    LibaryDao libaryDao;
  
  @Transaction(propagation=Propagation.REQUIRES_NEW)
  public int updateBook(String name,int price)
  {
     libaryDao.update(name,price);
  }
  
  @Transaction(propagation=Propagation.REQUIRES_NEW)
  public Book QueryBook(int Id)
  {
    libaryDao.QueryBook(Id);
  }
  
 //如下代碼只有errorway()會被當成一個事物。而下方的updateBook()和QueryBook()由於是調用了本類方法,沒有使用代理對象,因此不會通過事務處理。
 @Transaction
  public void errorway()
  {
    updateBook("三毛流浪記",56);
    QueryBook("射鵰英雄傳");
  }
相關文章
相關標籤/搜索