背景:面試被問到一個提,說說事務失效的場景,答的很不好,所以平時還是加強總結,發散思維,多做准備。
失效可能的原因
Spring 事務失效的8大原因
1、數據庫引擎是否支持事務(Myisam不支持事務)
2、注解所在的類是否被加載成Bean(對象沒有被Spring管理)
3、注解所在的方法是否為public修飾
4、是否發生了自身調用問題
5、所有數據源是否加載了事務管理器
6、@transaction的propagation配置是否正確
7、捕獲了異常
8、checked exceptions無效,需要配置rollbackFor = Throwable.class
9、只讀事務 只在
ps:交簡單的說明了幾種場景
拋出所有異常都會回滾嗎?_一口氣說出 6種,@Transactional注解的失效場景,面試官都蒙了...
ps通俗易懂
rollbackFor 可以指定能夠觸發事務回滾的異常類型。Spring默認拋出了未檢查unchecked異常(繼承自 RuntimeException 的異常)或者 Error才回滾事務;其他異常不會觸發回滾事務。如果在事務中拋出其他類型的異常,但卻期望 Spring 能夠回滾事務,就需要指定 rollbackFor屬性。
java中異常的分類
java里面將派生於Error或者RuntimeException(比如空指針,1/0)的異常稱為unchecked異常,
其他繼承自java.lang.Exception得異常統稱為Checked Exception,如IOException、TimeoutException等
ps:
public class RuntimeException extends Exception public class Exception extends Throwable
Exception中非RuntimeException的異常為checked 異常,編譯會無法通過
+-----------+ | Throwable | +-----------+ / \ / \ +-------+ +-----------+ | Error | | Exception | +-------+ +-----------+ / | \ / | \ \ \________/ \______/ \ +------------------+ unchecked checked | RuntimeException | +------------------+ / | | \ \_________________/ unchecked
辣么再通俗一點:你寫代碼出現的空指針等異常,會被回滾,文件讀寫,網絡出問題,spring就沒法回滾了。然后我教大家怎么記這個,因為很多同學容易弄混,你寫代碼的時候有些IOException我們的編譯器是能夠檢測到的,說以叫checked異常,你寫代碼的時候空指針等死檢測不到的,所以叫unchecked異常。這樣是不是好記一些啦
事務的傳播機制理解
ps:着重介紹了下面兩個傳播級別,結合例子很通俗易懂
PROPAGATION_REQUIRED
PROPAGATION_REQUIRES_NEW
案例二 PROPAGATION_REQUIRED
@Transactional @Override public void Example2(User user) { userMapper.insert(user); try { propagationService.required(); } catch (Exception e) { e.printStackTrace(); } } // 另一個service @Transactional @Override public void required() { throw new NullPointerException("肥朝假裝拋出了異常"); }
異常捕獲,是否會插入數據呢?
這個到底會不會插入數據呢?畢竟這個異常被try起來了。這個時候,正常的思維都會認為,能正常插入數據,但是答案是,不會插入數據,並且拋出異常
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
ps:這里是因為A B共用一個事務,A中的事務,在B拋出異常時候,被標記為回滾。最好看原文
案例二 PROPAGATION_REQUIRES_NEW
@Transactional @Override public void Example3(User user) { userMapper.insert(user); try { propagationService.requiresNew(); } catch (Exception e) { e.printStackTrace(); } } @Transactional(propagation = Propagation.REQUIRES_NEW) @Override public void requiresNew() { throw new NullPointerException("肥朝假裝拋出了異常"); }
答案是能插入數據
事務傳入機制的源碼實現
未完待續
事務中的屬性有哪些