spring事務有7種傳播行為,分別是:
1、PROPAGATION.REQUIRED:如果當前沒有事務,就創建一個新事務,如果當前存在事務,就加入該事務,該設置是最常用的設置。
2、PROPAGATION.SUPPORTS:支持當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就以非事務執行。‘
3、PROPAGATION.MANDATORY:支持當前事務,如果當前存在事務,就加入該事務,如果當前不存在事務,就拋出異常。
4、PROPAGATION.REQUIRES_NEW:創建新事務,無論當前存不存在事務,都創建新事務。
5、PROPAGATION.NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
6、PROPAGATION.NEVER:以非事務方式執行,如果當前存在事務,則拋出異常。
7、PROPAGATION.NESTED:如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。
注解@Transactional默認的傳播行為是:PROPAGATION.REQUIRED
若需要設置其他傳播行為,設置方法如下:
@Transactional(propagation = Propagation.REQUIRED) public void test() { //... }
上面的設置的作用是:當方法test出現 “運行時異常” 時,會進行事務回滾(其實是偽回滾,只是把之前的操作改回去。比如有插入操作且是主鍵是自增長的,假設插入一條記錄的操作前,下一id的值是1,但偽回滾后,就變成2了,也就是說,下一次成功插入后,id的值是2而不是1)。
但是如果,在test方法的方法體中捕獲了異常,則不會對事務進行回滾,代碼如下:
@Transactional public void test() { try{ //... } catch(DataAccessException e) { e.printStackTrace(); } }
上邊的代碼,如果對多個表進行操作,有成功也有失敗的操作,但最后,成功的操作不會被回滾,因為異常被捕獲了,spring捕獲不到,也就沒辦法回滾了。
要想既捕獲異常然后做一些操作,又想對失敗的操作進行回滾,可以在捕獲異常后,再對異常拋出,即讓spring能捕獲該異常 ,示例如下:
@Transactional public void test() { try{ //... } catch(DataAccessException e) { e.printStackTrace(); throw e; } }
另外,被@Transactional注解的方法,spring不止對捕獲數據訪問異常才會進行回滾,而是只要捕獲到了運行時異常都會進行回滾,比如下面的示例:
@Transactional public void test() { try{ //... int [] counts = new int[]{1}; int count = counts[1]; } catch(RuntimeException e) { e.printStackTrace(); throw e; } }
上邊的代碼,會報數組下標越界的“運行時異常” ,但被捕獲了,就算之前對數據庫的操作是成功的,之前對數據庫的操作還是會被回滾。
暫時到這里,以后遇到新問題再補充。