Spring Boot的事務管理註解@EnableTransactionManagement的使用
Spring Boot 使用事務非常簡單,首先使用註解 @EnableTransactionManagement 開啟事務支援後,然後在訪問資料庫的Service方法上添加註解 @Transactional 便可。
關於事務管理器,不管是JPA還是JDBC等都實現自介面 PlatformTransactionManager 如果你新增的是 spring-boot-starter-jdbc 依賴,框架會預設注入 DataSourceTransactionManager 例項。如果你新增的是 spring-boot-starter-data-jpa 依賴,框架會預設注入 JpaTransactionManager 例項。
你可以在啟動類中新增如下方法,Debug測試,就能知道自動注入的是 PlatformTransactionManager 介面的哪個實現類。
@EnableTransactionManagement // 啟註解事務管理,等同於xml配置方式的 <tx:annotation-driven />
@SpringBootApplication
public class ProfiledemoApplication {
@Bean
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為我們自動做了,這些對我們並不透明,如果你專案做的比較大,新增的持久化依賴比較多,我們還是會選擇人為的指定使用哪個事務管理器。
程式碼如下:
@EnableTransactionManagement
@SpringBootApplication
public class ProfiledemoApplication {
// 其中 dataSource 框架會自動為我們注入
@Bean
public PlatformTransactionManager txManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
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 註解的方法,將支援事務。如果註解在類上,則整個類的所有方法都預設支援事務。
對於同一個工程中存在多個事務管理器要怎麼處理,請看下面的例項,具體說明請看程式碼中的註釋。
@EnableTransactionManagement // 開啟註解事務管理,等同於xml配置檔案中的 <tx:annotation-driven />
@SpringBootApplication
public class ProfiledemoApplication implements TransactionManagementConfigurer {
@Resource(name="txManager2")
private PlatformTransactionManager txManager2;
// 建立事務管理器1
@Bean(name = "txManager1")
public PlatformTransactionManager txManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
// 建立事務管理器2
@Bean(name = "txManager2")
public PlatformTransactionManager txManager2(EntityManagerFactory factory) {
return new JpaTransactionManager(factory);
}
// 實現介面 TransactionManagementConfigurer 方法,其返回值代表在擁有多個事務管理器的情況下預設使用的事務管理器
@Override
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
@Component
public class DevSendMessage implements SendMessage {
// 使用value具體指定使用哪個事務管理器
@Transactional(value="txManager1")
@Override
public void send() {
System.out.println(">>>>>>>>Dev Send()<<<<<<<<");
send2();
}
// 在存在多個事務管理器的情況下,如果使用value具體指定
// 則預設使用方法 annotationDrivenTransactionManager() 返回的事務管理器
@Transactional
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,這樣控制檯會明確丟擲異常,開發人員就不會忘記主動指定。