一、開啟事物管理
//import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement //顯示開啟事物管理,springboot默認已經開啟事物管理,可不用顯示的注解 public class Application extends SpringBootServletInitializer { @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(Application.class); } public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
二、配置事物
在需要事物的類或方法上使用@Transactional(import org.springframework.transaction.annotation.Transactional)
1、isolation 隔離級別(Springboot默認值為Isolation.DEFAULT)
用法:
@Transactional(isolation=Isolation.DEFAULT) public void test() { }
枚舉值(org.springframework.transaction.annotation):
public enum Isolation { DEFAULT(TransactionDefinition.ISOLATION_DEFAULT), READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED), READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED), REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ), SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE); }
DEFAULT
:默認值,表示使用底層數據庫的默認隔離級別。大部分數據庫為READ_COMMITTED(MySql默認隔離級別為REPEATABLE)
READ_UNCOMMITTED
:該隔離級別表示一個事務可以讀取另一個事務修改但還沒有提交的數據。該級別不能防止臟讀和不可重復讀,因此很少使用該隔離級別。 READ_COMMITTED
:該隔離級別表示一個事務只能讀取另一個事務已經提交的數據。該級別可以防止臟讀,這也是大多數情況下的推薦值。 REPEATABLE_READ
:該隔離級別表示一個事務在整個過程中可以多次重復執行某個查詢,並且每次返回的記錄都相同。即使在多次查詢之間有新增的數據滿足該查詢,這些新增的記錄也會被忽略。該級別可以防止臟讀和不可重復讀。 SERIALIZABLE
:所有的事務依次逐個執行,這樣事務之間就完全不可能產生干擾,也就是說,該級別可以防止臟讀、不可重復讀以及幻讀。但是這將嚴重影響程序的性能。通常情況下也不會用到該級別。
通過使用 isolation
屬性設置,例如:@Transactional(isolation = Isolation.DEFAULT)/2.
2、事物傳播行為 propagation(springboot默認值為Propagation.REQUIRED)
用法
@Transactional(propagation=Propagation.REQUIRED) public void test() { }
枚舉值(org.springframework.transaction.annotation.Propagation)
public enum Propagation { REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED), SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS), MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY), REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW), NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED), NEVER(TransactionDefinition.PROPAGATION_NEVER), NESTED(TransactionDefinition.PROPAGATION_NESTED); }
REQUIRED
:如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務。 SUPPORTS
:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行。 MANDATORY
:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。 REQUIRES_NEW
:創建一個新的事務,如果當前存在事務,則把當前事務掛起。 NOT_SUPPORTED
:以非事務方式運行,如果當前存在事務,則把當前事務掛起。 NEVER
:以非事務方式運行,如果當前存在事務,則拋出異常。 NESTED
:如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價於 REQUIRED
。
指定方法:通過使用 propagation
屬性設置,例如:@Transactional(propagation = Propagation.REQUIRED)
Spring定義了七種傳播行為:
3、readOnly=true只讀,不能更新,刪除
@Transactional(readOnly=true)
三、常見坑點
1、遇到異常檢測不回滾,原因:默認RuntimeException級別才回滾,如果是Eexception級別的異常需要手動添加
@Transactional(rollbackFor=Exception.class)
2、捕捉異常后事物不生效,原因:捕捉處理了異常導致框架無法感知異常,自然就無法回滾了。建議:若非實際業務要求,則在業務層統一拋出異常,然后在控制層統一處理
@Transactional(rollbackFor=Exception.class) public void test() { try { //業務代碼 } catch (Exception e) { // TODO: handle exception }
//主動捕捉異常導致框架無法捕獲,從而導致事物失效 }
參考1:https://blog.csdn.net/weixin_39625809/article/details/80707695