Spring 爲事務管理提供了豐富的功能支持。Spring 事務管理分爲編程式和聲明式的兩種方式。編程式事務指的是經過編碼方式實現事務;聲明式事務基於 AOP,將具體業務邏輯與事務處理解耦。聲明式事務管理使業務代碼邏輯不受污染, 所以在實際使用中聲明式事務用的比較多。聲明式事務有兩種方式,一種是在配置文件(xml)中作相關的事務規則聲明,另外一種是基於 @Transactional 註解的方式。html
須要明確聲明式事物的前提:java
@Transactional
註解便可, spring boot 會自動配置一個 DataSourceTransactionManager
,可配置屬性異常複習:spring
非運行時異常(除RuntimeException之外),如IOException,SQLException等等,必須使用catch進行捕獲,不然程序就沒法經過;由於異常被捕獲,因此沒法發生回滾;sql
經過配置propagation
屬性,能夠選擇事務的傳播行爲數據庫
可選的值有:編程
Propagation.REQUIRED(默認)app
若是當前存在事務,則加入該事務,若是當前不存在事務,則建立一個新的事務。ide
使用示例:spring-boot
@Transactional(propagation = Propagation.REQUIRED)
@Override
public int insertExample(AccompanyRecord accompanyRecord) {
Student student = new Student();
// myabtis接口
studentMapper.updateAttention(student);
accompanyRecordMapper.insertAccompanyRecord(accompanyRecord);
if (true) {
// 拋異常 回滾
throw new RuntimeException();
}
}
複製代碼
以上兩條sql執行完後,又拋出了運行時異常,因此上面兩條sql都會進行回滾;編碼
Propagation.SUPPORTS
若是當前存在事務,則加入該事務;若是當前不存在事務,則以非事務的方式繼續運行。
Propagation.MANDATORY
若是當前存在事務,則加入該事務;若是當前不存在事務,則拋出異常。
Propagation.REQUIRES_NEW
從新建立一個新的事務,若是當前存在事務,暫停當前的事務。
Propagation.NOT_SUPPORTED
以非事務的方式運行,若是當前存在事務,暫停當前的事務。
Propagation.NEVER
以非事務的方式運行,若是當前存在事務,則拋出異常。
Propagation.NESTED
和 Propagation.REQUIRED 效果同樣。
事務使用的注意事項:
在默認的代理模式下,只有目標方法由外部調用,才能被 Spring 的事務攔截器攔截。在同一個類中的兩個方法直接調用,是不會被 Spring 的事務攔截器攔截;【參照Spring官方文檔】
示例:
在有需求以下,就算 save 方法的後面拋異常了,也不能影響 method1 方法的數據插入。直接給 method1 頁加入一個新的事務,這樣 method1 就會在這個新的事務中執行,原來的事務不會影響到新的事務。好比 method1 方法上面再加入註解 @Transactional,設置 propagation 屬性爲 Propagation.REQUIRES_NEW,代碼以下。
@Transactional(propagation = Propagation.REQUIRED)
@Override
public void save() {
method1();
User user = new User("服部半藏");
userMapper.insertSelective(user);
if (true) {
throw new RuntimeException("save 拋異常了");
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void method1() {
User user = new User("宮本武藏");
userMapper.insertSelective(user);
}
複製代碼
此時會發現,即便拋出異常了,仍然發生回滾;經過日誌能夠發現,從頭至尾都只有一個事物,並無建立新事物;因此咱們要想建立新事物,必須新建一個類,將該方法由外部調用,也就是新建一個類用於存放method1便可;此時會發現能夠按照需求執行;
流程:@Transactional 的 propagation 屬性爲 Propagation.REQUIRES_NEW ,因此接着暫停了 save 方法的事務,從新建立了xxx.method1 方法的事務,接着 xxx.method1 方法的事務提交,接着 save 方法的事務回滾。
經過配置isolation
屬性,能夠選擇事務的隔離級別
可選的值有:
Isolation.DEFAULT(默認)
使用底層數據庫默認的隔離級別。
Isolation.READ_UNCOMMITTED
Isolation.READ_COMMITTED
Isolation.REPEATABLE_READ
Isolation.SERIALIZABLE
timeout 屬性 事務的超時時間,默認值爲-1。若是超過該時間限制但事務尚未完成,則自動回滾事務。
readOnly 屬性 指定事務是否爲只讀事務,默認值爲 false;爲了忽略那些不須要事務的方法,好比讀取數據,能夠設置 read-only 爲 true。
rollbackFor 屬性 用於指定可以觸發事務回滾的異常類型,能夠指定多個異常類型。
noRollbackFor 屬性 拋出指定的異常類型,不回滾事務,也能夠指定多個異常類型。
注:alibaba規範必須顯示聲明RollBackFor:
讓checked例外也回滾:在整個方法前加上 @Transactional(rollbackFor=Exception.class)
讓unchecked例外不回滾: @Transactional(notRollbackFor=RunTimeException.class)
不須要事務管理的(只查詢的)方法:@Transactional(propagation=Propagation.NOT_SUPPORTED)
注意: 若是異常被try{}catch{}了,事務就不回滾了,若是想讓事務回滾必須再往外拋try{}catch{throw Exception}。
基於AOP,暫略