關(guān)系型數(shù)據(jù)庫多用到事務(wù),在傳統(tǒng)項目中使用xml配置,配置雖然也還好,但是看著很不美觀,在使用SpringBoot框架,就簡單的多了,以實戰(zhàn)為準(zhǔn),直接上代碼
@Transactional
spring 事務(wù)注解
1.簡單開啟事務(wù)管理
@EnableTransactionManagement // 啟注解事務(wù)管理,等同于xml配置方式的 <tx:annotation-driven />
2.事務(wù)注解詳解
默認遇到throw new RuntimeException("...");會回滾
需要捕獲的throw new Exception("...");不會回滾
- 指定回滾
@Transactional(rollbackFor=Exception.class)
public void methodName() {
// 不會回滾
throw new Exception("...");
}
- 指定不回滾
@Transactional(noRollbackFor=Exception.class)
public ItimDaoImpl getItemDaoImpl() {
// 會回滾
throw new RuntimeException("注釋");
}
- 如果有事務(wù),那么加入事務(wù),沒有的話新建一個(不寫的情況下)
@Transactional(propagation=Propagation.REQUIRED)
- 容器不為這個方法開啟事務(wù)
@Transactional(propagation=Propagation.NOT_SUPPORTED)
- 不管是否存在事務(wù),都創(chuàng)建一個新的事務(wù),原來的掛起,新的執(zhí)行完畢,繼續(xù)執(zhí)行老的事務(wù)
@Transactional(propagation=Propagation.REQUIRES_NEW)
- 必須在一個已有的事務(wù)中執(zhí)行,否則拋出異常
@Transactional(propagation=Propagation.MANDATORY)
- 必須在一個沒有的事務(wù)中執(zhí)行,否則拋出異常(與Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.NEVER)
- 如果其他bean調(diào)用這個方法,在其他bean中聲明事務(wù),那就用事務(wù).如果其他bean沒有聲明事務(wù),那就不用事務(wù).
@Transactional(propagation=Propagation.SUPPORTS)
/*
public void methodName(){
// 本類的修改方法 1
update();
// 調(diào)用其他類的修改方法
otherBean.update();
// 本類的修改方法 2
update();
}
other失敗了不會影響 本類的修改提交成功
本類update的失敗,other也失敗
*/
@Transactional(propagation=Propagation.NESTED)
- readOnly=true只讀,不能更新,刪除
@Transactional (propagation = Propagation.REQUIRED,readOnly=true)
- 設(shè)置超時時間
@Transactional (propagation = Propagation.REQUIRED,timeout=30)
- 設(shè)置數(shù)據(jù)庫隔離級別
@Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT)
3.指定事務(wù)管理器
spring Boot 使用事務(wù)非常簡單,首先使用注解 @EnableTransactionManagement 開啟事務(wù)支持后,然后在訪問數(shù)據(jù)庫的Service方法上添加注解 @Transactional 便可。
關(guān)于事務(wù)管理器,不管是JPA還是JDBC等都實現(xiàn)自接口 PlatformTransactionManager 如果你添加的是 spring-boot-starter-jdbc 依賴,框架會默認注入 DataSourceTransactionManager 實例。如果你添加的是 spring-boot-starter-data-jpa 依賴,框架會默認注入 JpaTransactionManager 實例。
你可以在啟動類中添加如下方法,Debug測試,就能知道自動注入的是 PlatformTransactionManager 接口的哪個實現(xiàn)類。
3.1 打印項目事務(wù)管理器
@EnableTransactionManagement // 啟注解事務(wù)管理,等同于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);
}
}
這些SpringBoot為我們自動做了,這些對我們并不透明,如果你項目做的比較大,添加的持久化依賴比較多,我們還是會選擇人為的指定使用哪個事務(wù)管理器。
代碼如下:
3.2 指定事務(wù)管理器
@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);
}
}
在Spring容器中,我們手工注解@Bean 將被優(yōu)先加載,框架不會重新實例化其他的 PlatformTransactionManager 實現(xiàn)類。
然后在Service中,被 @Transactional 注解的方法,將支持事務(wù)。如果注解在類上,則整個類的所有方法都默認支持事務(wù)。
對于同一個工程中存在多個事務(wù)管理器要怎么處理,請看下面的實例,具體說明請看代碼中的注釋。
3.1 使用指定的事務(wù)管理器
@EnableTransactionManagement // 開啟注解事務(wù)管理,等同于xml配置文件中的 <tx:annotation-driven />
@SpringBootApplication
public class ProfiledemoApplication implements TransactionManagementConfigurer {
@Resource(name="txManager2")
private PlatformTransactionManager txManager2;
// 創(chuàng)建事務(wù)管理器1
@Bean(name = "txManager1")
public PlatformTransactionManager txManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
// 創(chuàng)建事務(wù)管理器2
@Bean(name = "txManager2")
public PlatformTransactionManager txManager2(EntityManagerFactory factory) {
return new JpaTransactionManager(factory);
}
// 實現(xiàn)接口 TransactionManagementConfigurer 方法,其返回值代表在擁有多個事務(wù)管理器的情況下默認使用的事務(wù)管理器
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return txManager2;
}
public static void main(String[] args) {
SpringApplication.run(ProfiledemoApplication.class, args);
}
}
@Component
public class DevSendMessage implements SendMessage {
// 使用value具體指定使用哪個事務(wù)管理器
@Transactional(value="txManager1")
@Override
public void send() {
System.out.println(">>>>>>>>Dev Send()<<<<<<<<");
send2();
}
// 在存在多個事務(wù)管理器的情況下,如果使用value具體指定
// 則默認使用方法 annotationDrivenTransactionManager() 返回的事務(wù)管理器
@Transactional
public void send2() {
System.out.println(">>>>>>>>Dev Send2()<<<<<<<<");
}
}