Spring Boot 使用事務非常簡單,首先使用注解 @EnableTransactionManagement 開啟事務支持后,然后在訪問數據庫的Service方法上添加注解 @Transactional 便可。
關於事務管理器,不管是JPA還是JDBC等都實現自接口 PlatformTransactionManager 如果你添加的是 spring-boot-starter-jdbc 依賴,框架會默認注入 DataSourceTransactionManager 實例。如果你添加的是 spring-boot-starter-data-jpa 依賴,框架會默認注入 JpaTransactionManager 實例。
你可以在啟動類中添加如下方法,Debug測試,就能知道自動注入的是 PlatformTransactionManager 接口的哪個實現類。
-
-
-
public class ProfiledemoApplication {
-
-
-
public Object testBean(PlatformTransactionManager platformTransactionManager){
-
System.out.println( ">>>>>>>>>>" + platformTransactionManager.getClass().getName());
-
return new Object();
-
}
-
-
public static void main(String[] args) {
-
SpringApplication.run(ProfiledemoApplication.class, args);
-
}
-
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
這些SpringBoot為我們自動做了,這些對我們並不透明,如果你項目做的比較大,添加的持久化依賴比較多,我們還是會選擇人為的指定使用哪個事務管理器。
代碼如下:
-
-
-
public class ProfiledemoApplication {
-
-
// 其中 dataSource 框架會自動為我們注入
-
-
public PlatformTransactionManager txManager(DataSource dataSource) {
-
return new DataSourceTransactionManager(dataSource);
-
}
-
-
-
public Object testBean(PlatformTransactionManager platformTransactionManager) {
-
System.out.println( ">>>>>>>>>>" + platformTransactionManager.getClass().getName());
-
return new Object();
-
}
-
-
public static void main(String[] args) {
-
SpringApplication.run(ProfiledemoApplication.class, args);
-
}
-
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
在Spring容器中,我們手工注解@Bean 將被優先加載,框架不會重新實例化其他的 PlatformTransactionManager 實現類。
然后在Service中,被 @Transactional 注解的方法,將支持事務。如果注解在類上,則整個類的所有方法都默認支持事務。
對於同一個工程中存在多個事務管理器要怎么處理,請看下面的實例,具體說明請看代碼中的注釋。
-
-
-
public class ProfiledemoApplication implements TransactionManagementConfigurer {
-
-
-
private PlatformTransactionManager txManager2;
-
-
// 創建事務管理器1
-
-
public PlatformTransactionManager txManager(DataSource dataSource) {
-
return new DataSourceTransactionManager(dataSource);
-
}
-
-
// 創建事務管理器2
-
-
public PlatformTransactionManager txManager2(EntityManagerFactory factory) {
-
return new JpaTransactionManager(factory);
-
}
-
-
// 實現接口 TransactionManagementConfigurer 方法,其返回值代表在擁有多個事務管理器的情況下默認使用的事務管理器
-
-
public PlatformTransactionManager annotationDrivenTransactionManager() {
-
return txManager2;
-
}
-
-
public static void main(String[] args) {
-
SpringApplication.run(ProfiledemoApplication.class, args);
-
}
-
-
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
-
-
-
public class DevSendMessage implements SendMessage {
-
-
// 使用value具體指定使用哪個事務管理器
-
-
-
public void send() {
-
System.out.println( ">>>>>>>>Dev Send()<<<<<<<<");
-
send2();
-
}
-
-
// 在存在多個事務管理器的情況下,如果使用value具體指定
-
// 則默認使用方法 annotationDrivenTransactionManager() 返回的事務管理器
-
-
public void send2() {
-
System.out.println( ">>>>>>>>Dev Send2()<<<<<<<<");
-
}
-
-
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
注:
如果Spring容器中存在多個 PlatformTransactionManager 實例,並且沒有實現接口 TransactionManagementConfigurer 指定默認值,在我們在方法上使用注解 @Transactional 的時候,就必須要用value指定,如果不指定,則會拋出異常。
對於系統需要提供默認事務管理的情況下,實現接口 TransactionManagementConfigurer 指定。
對有的系統,為了避免不必要的問題,在業務中必須要明確指定 @Transactional 的 value 值的情況下。不建議實現接口 TransactionManagementConfigurer,這樣控制台會明確拋出異常,開發人員就不會忘記主動指定。