事務@Transactional注解的屬性


事務的傳播行為

當事務方法被另一個事務方法調用時,必須指定事務應該如何傳播。例如:方法可能繼續在現有事務中運行,也可能開啟一個新事務,並在自己的事務中運行。
事務的傳播行為可以由傳播屬性指定。Spring定義了7種類傳播行為。

事務傳播屬性可以在@Transactional注解的propagation屬性中定義。

1) . 說明
  ①REQUIRED傳播行為
當bookService的purchase()方法被另一個事務方法checkout()調用時,它默認會在現有的事務內運行。這個默認的傳播行為就是REQUIRED。因此在checkout()方法的開始和終止邊界內只有一個事務。這個事務只在checkout()方法結束的時候被提交,結果用戶一本書都買不了。
 

②. REQUIRES_NEW傳播行為
表示該方法必須啟動一個新事務,並在自己的事務內運行。如果有事務在運行,就應該先掛起它。

事務的隔離級別

1、數據庫事務並發問題
   假設現在有兩個事務:Transaction01和Transaction02並發執行。
  1) 臟讀(針對一條數據中的一個字段)
     ①Transaction01將某條記錄的AGE值從20修改為30。
     ②Transaction02讀取了Transaction01更新后的值:30。
     ③Transaction01回滾,AGE值恢復到了20。
     ④Transaction02讀取到的30就是一個無效的值。
  2) 不可重復讀(針對一條數據中的一個字段)
     ①Transaction01讀取了AGE值為20。
     ②Transaction02將AGE值修改為30。
     ③Transaction01再次讀取AGE值為30,和第一次讀取不一致。
  3) 幻讀(針對表中的一行數據而言)
     ①Transaction01讀取了STUDENT表中的一部分數據。
     ②Transaction02向STUDENT表中插入了新的行。
     ③Transaction01讀取了STUDENT表時,多出了一些行。
2、 隔離級別
數據庫系統必須具有隔離並發運行各個事務的能力,使它們不會相互影響,避免各種並發問題。一個事務與其他事務隔離的程度稱為隔離級別。SQL標准中規定了多種事務隔離級別,不同隔離級別對應不同的干擾程度,隔離級別越高,數據一致性就越好,但並發性越弱。
  1) 讀未提交:READ UNCOMMITTED
    允許Transaction01讀取Transaction02未提交的修改。
  2) 讀已提交:READ COMMITTED
     要求Transaction01只能讀取Transaction02已提交的修改。
  3) 可重復讀:REPEATABLE READ
       確保Transaction01可以多次從一個字段中讀取到相同的值,即Transaction01執行期間禁止其它事務對這個字段進行更新。
  4) 串行化:SERIALIZABLE
      確保Transaction01可以多次從一個表中讀取到相同的行,在Transaction01執行期間,禁止其它事務對這個表進行添加、更新、刪除操作。可以避免任何並發問題,但性能十分低下。(單線程,在一個請求中,其他線程讀都不可以)

用@Transactional注解聲明式地管理事務時可以在@Transactional的isolation屬性中設置隔離級別。

觸發事務回滾的異常
1、默認情況
捕獲到RuntimeException或Error時回滾,而捕獲到編譯時異常不回滾。
2、設置途經
1) 注解@Transactional 注解
 ① rollbackFor屬性:指定遇到時必須進行回滾的異常類型,可以為多個
 ② noRollbackFor屬性:指定遇到時不回滾的異常類型,可以為多個

 

 

事務的超時和只讀屬性

1、簡介
 由於事務可以在行和表上獲得鎖,因此長事務會占用資源,並對整體性能產生影響。 如果一個事務只讀取數據但不做修改,數據庫引擎可以對這個事務進行優化。
 超時事務屬性:事務在強制回滾之前可以保持多久。這樣可以防止長期運行的事務占用資源。
 只讀事務屬性: 表示這個事務只讀取數據但不更新數據, 這樣可以幫助數據庫引擎優化事務。
2、注解設置
@Transaction注解

package com.atguigu.book.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.atguigu.book.dao.BookDao;
import com.atguigu.book.exception.MyException;
import com.atguigu.book.service.BookService;

@Service
//@Transactional
public class BookServiceImpl implements BookService {

    @Autowired
    private BookDao dao;
    
    /**
     * @Transactional:對方法中所有的操作作為一個事務進行管理
     * 在方法上使用,只對方法有效果
     * 在類上使用,對類中所有的方法都有效果
     * @Transactional中可以設置的屬性:
     * 
     * propagation:A方法和B方法都有事務,當A在調用B時,會將A中的事務傳播給B方法,B方法對於事務的處理方式就是事務的傳播行為
     *         Propagation.REQUIRED:必須使用調用者的事務(默認值)
     *         Propagation.REQUIRES_NEW:將調用者的事務掛起,不使用調用者的事務,使用新的事務進行處理
     * 
     * isolation:事務的隔離級別,在並發的情況下,操作數據的一種規定
     *             讀未提交:臟讀   1
     *             讀已提交:不可重復讀   2
     *             可重復讀:幻讀   4
     *             串行化:性能低,消耗大   8
     * 
     * 
     * timeout:在事務強制回滾前最多可以執行(等待)的時間
     * 
     * readOnly:指定當前事務中的一系列的操作是否為只讀
     * 若設置為只讀,不管事務中有沒有寫的操作,mysql都會在請求訪問數據的時候,不加鎖,提高性能
     * 但是如果有寫操作的情況,建議一定不能設置只讀
     * 
     * rollbackFor|rollbackForClassName|noRollbackFor|noRollbackForClassName:設置事務回滾的條件
     */
    
    @Transactional(propagation=Propagation.REQUIRES_NEW, timeout=3, noRollbackFor= {NullPointerException.class, MyException.class})
    public void buyBook(String bid, String uid) {
        /*try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }*/
        Integer price = dao.selectPrice(bid);
        dao.updateSt(bid);
        dao.updateBalance(uid, price);
    }
}

 


 
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM