Spring中的事務管理

配置註解

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

建立事務bean,配置數據源屬性html

<tx:annotation-driven transaction-manager="transactionManager" /> 

事務註解驅動java

 

聲明式事務

@Transactional
public void hasTranInsertData() {
    Book book = new Book();
        
    book.setIsbn("0002");
    book.setBookName("java編程思想");
    book.setPrice(79);
        
    this.bookMapper.insertSelective(book);
        
    int i = 1 / 0;
}
public void notHasTranInsertData() {
    Book book = new Book();
        
    book.setIsbn("0003");
    book.setBookName("算法導論");
    book.setPrice(109);
        
    this.bookMapper.insertSelective(book);
        
    int i = 1 / 0;
}

以上能夠看出上面的數據回滾了,而下面的保存到數據庫了。mysql

 

事務的傳播

REQUIRED 若是現有的事務正在進行,當前方法應該在這個事務中運行,不然它該啓動新事務,並在本身的十五中運行。
REQUIRES_NEW 當前方法必須啓動新事務,並在本身的事務中運行,若是現有的事務正在進行,它應該掛起。
SUPPORTS 若是現有事務正在進行,當前方法應該運行在該事務中,不然它沒有必要運行在事務中。
NOT_SUPPORTED 當前方法不該該運行在事務中,若是現有事務正在運行,它應該掛起。
MANDATORY 當前方法必須運行於事務中,若是沒有事務在進行中,將拋出一個異常。
NEVER 當前方法不該該運行於事務中,若是現有事務在運行中,將拋出一個異常。
NESTED 若是現有事務正在進行,當前方法應該運行在嵌套的事務中,不然它應該啓動一個新事務並運行在本身的事務之中。

 

 

 

 

 

 

 

例如:算法

@Override
@Transactional
public void nestedBook() {
        
    Book book = new Book();
        
    book.setIsbn("0004");
    book.setBookName("分佈式架構");
    book.setPrice(89);
        
    this.bookMapper.insertSelective(book);
        
    for (int i = 0; i < 10; i ++) {
        try {
            this.testService1.nestedAccount(i + 2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
        
}
@Override
@Transactional(propagation=Propagation.NESTED)
public void nestedAccount(int i) {
    System.out.println(i);
    Account account = new Account();
    account.setUsername("user" + i);
    account.setBalance(new Random().nextInt(100));
        
    this.accountMapper.insertSelective(account);
        
    if (7 == i) {
        int j = 1 / 0;
    }
}

這裏一個REQUIRED事務去調用NESTED事務,NESTED特性是在嵌套的事務裏,若是發生異常他只會回滾他本身的事務,而不會影響調用他的事務。spring

他與REQUIRES_NEW的區別是,前面方法沒有事務是每次須要建立本身的事務,若是前面有事務時,前面方法若是報錯了會回滾全部操做,而REQUIRES_NEW不會回滾操做。sql

NESTED的好處在於既能保證前者方法拋異常時全部數據能回滾,也能保證後者方法一個拋異常不會影響後續的操做,只會回滾後者操做失敗的數據。數據庫

 

隔離事務

DEFAULT 使用底層數據庫的默認隔離級別。對於大部分數據庫,默認隔離級別是READ_COMMITED,mysql是REPEATABLE_READ
READ_UNCOMMITED 容許事務讀取其餘事務的未提交修改。可能發生髒讀數據、不可重複讀幻讀問題。
READ_COMMITED  僅容許事務讀取其餘事務已經提交的修改。可以避免髒讀數據問題,可是不可重複讀幻讀問題仍然可能發生。
REPEATABLE_READ 確保事務可以屢次從一個字段讀到相同值。在本事務期間,其餘事務的更新被禁止。可以避免髒讀數據和不可重複讀問題,可是幻讀問題仍然可能發生。
SERIALIZABLE 確保一個事務能從表中屢次讀取相同的行。在事務期間,其餘事務作出的對該表插入、更新和刪除將被禁止。能避免全部併發性問題,可是性能將會很

 

 

 

 

 

 

 

 

RollBack屬性

默認狀況下,只有非受控異常(也就是RuntimeExceptionError類型)將致使事務回滾,而受控異常不會。編程

@Override
@Transactional
public void hasTranInsertData() throws FileNotFoundException, ClassNotFoundException {
    Book book = new Book();
        
    book.setIsbn("0005");
    book.setBookName("java編程思想");
    book.setPrice(79);
        
    this.bookMapper.insertSelective(book);
        
    try {
        int i = 1 / 0;
    } catch (Exception e) {
        throw new FileNotFoundException("錯誤");
    }
}

嚴重警告:上面的這段代碼是不會回滾的,就由於拋出的異常時受控異常架構

 

rollbackFor:會發生回滾的異常併發

noRollbackFor:不會發生回滾的異常

將@Transaction變爲下面這樣

@Transactional(rollbackFor=FileNotFoundException.class, noRollbackFor=ClassNotFoundException.class)

改變以後就會進行回滾

若是拋出的異常改成

throw new ClassNotFoundException("錯誤");

則又不會回滾

 

超時和只讀

timeout:表示事務在被強制回滾以前存活的時間。這可以避免長時間的事務佔用資源。

readOnly:表示該事務僅僅讀取而不更新數據。只讀標誌只是讓資源優化事務的一個提醒,若是試圖寫入,資源不必定會發生故障。

相關文章
相關標籤/搜索