人人妻人人澡人人爽人人精品av_精品乱码一区内射人妻无码_老司机午夜福利视频_精品成品国色天香摄像头_99精品福利国产在线导航_野花社区在线观看视频_大地资源在线影视播放_东北高大肥胖丰满熟女_金门瓶马车内剧烈运动

首頁>國內(nèi) > 正文

快播:總結(jié)一下Spring中事務(wù)失效的八種場景

2023-07-05 13:24:23來源:JAVA日知錄

1. 數(shù)據(jù)庫引擎不支持事務(wù)

這里以 MySQL為例,MyISAM引擎是不支持事務(wù)操作的,一般要支持事務(wù)都會使用InnoDB引擎,根據(jù)MySQL 的官方文檔說明,從MySQL 5.5.5 開始的默認(rèn)存儲引擎是 InnoDB,之前默認(rèn)的都是 MyISAM,所以這一點(diǎn)要值得注意,如果底層引擎不支持事務(wù),那么再怎么設(shè)置也沒有用。

2.沒有被 Spring 管理

示例如下:


(資料圖片僅供參考)

public class OrderServiceImpl implements OrderService{  @Transactional  public void updateOrder(Order order){    //update order  }}

如果此時把@Service注解注釋掉,那么這個類就不會被加載成一個Bean,這個類就不會Spring管理了,事務(wù)自然就失效了。

3. 方法不是 public 的

@Transactional注解只能用干public 的方法上,否則事多不會生效,如果要用在非public的方法上,則可以開啟基于 AspcetJ 框架的靜態(tài)代理模式。

4.發(fā)生自身調(diào)用

示例如下:

@Servicepublic class OrderServiceImpl implements OrderService {  public void update(Order order) {    updateOrder(order);  }}@Transactionalpublic void updateOrder(0rder order) {    // update order  }}

update 方法上面沒有加@Transactional注解,如果調(diào)用有@Transactional注解的updateOrder 方法,那么 updateOrder 方法上的事務(wù)還可以生效嗎? 這里大家可以先想一想,后面會揭曉答案。

再來看下面這個例子:

@Servicepublic class OrderServiceImpl implements OrderService {  @Transactional  public void update(Order order) {    updateOrder(order);  }}@Transactional(propagation = Propagation.REQUIRES_NEW)public void updateOrder(0rder order) {     updateOrder(order);  }}

這次在 update 方法上加了@Transactional, 如果在 updateOrder 上加了REOUIRES_NEW新開啟一個事務(wù),那么新開啟的事務(wù)可以生效嗎?

這兩個例子中的事務(wù)都不會生效,因?yàn)樗鼈儼l(fā)生了自身調(diào)用,就調(diào)用了該類自己的方法,而沒有經(jīng)過Spring的代理類,默認(rèn)只有調(diào)用外部代理類的方法,事務(wù)才會生效,這也是老生常談的問題了。

這個問題的解決方案之一就是在事務(wù)所在的類中注入自己,用往入的對象再調(diào)用另外一個方法,這個不太優(yōu)雅,在Spring 中可以在當(dāng)前線程中暴露并獲取當(dāng)前代理類,通過在啟動類上添加以下注解來啟用暴露代理類,如下面的示例所示。

@EnableAspectJAutoProxy(exposeProxy = true)

然后通過以下代碼獲取當(dāng)前代理類,并調(diào)用代理類的事務(wù)方法:

((0rderService) AopContext.currentProxy()).updateOrder();

Spring 默認(rèn)只有調(diào)用 Spring代理類的public 方法,事務(wù)才能生效。

5.沒有配置事務(wù)管理器

如果沒有配置以下DataSourceTransactionManager數(shù)據(jù)源事務(wù)管理器,那么事務(wù)也不會生效 :

@Beanpublic PlatformTransactionManager transactionManager(DataSource dataSource) {  return new DataSourceTransactionManager(dataSource);}

但在 Spring Boot 中只要引入了spring-boot-starter-data-jdbc啟動器依賴就會自動配置DataSourceTransactionManager數(shù)據(jù)源事務(wù)管理器,所以 Spring Boot框架不存在這個問題,但在傳統(tǒng)的 Spring 框架中需要注意。

6. 設(shè)置了不支持事務(wù)

示例如下:

@Servicepublic class OrderServiceImpl implements OrderService {  @Transactional  public void update(Order order) {    updateOrder(order);  }    @Transactional(propagation = Propagation.NOT_SUPPORTED)  public void updateOrder(Order order) {    //update order  }}

這里的Propagation.NOT_SUPPORTED表示當(dāng)前方法不以事務(wù)方式運(yùn)行,當(dāng)前若存在事務(wù)則掛起,這就是主動不支持以事務(wù)方式運(yùn)行了。

7. 異常沒有被拋出

示例如下:

@Servicepublic class OrderServiceImpl implements OrderService {  @Transactional  public void update(Order order) {    try{      // update order    }catch{          }  }}

這個方法把異常給捕獲了,但沒有拋出來,所以事務(wù)不會回滾,只有捕捉到異常事務(wù)才會生效。

8. 異常類型不匹配

示例如下:

@Servicepublic class OrderServiceImpl implements OrderService {  @Transactional  public void update(Order order) {    try{      // update order    }catch{      throw new Exception("更新失敗");    }  }}

因?yàn)?Spring 默認(rèn)回滾的是 RuntimeException 異常,和程序拋出的 Exception 異常不匹配,所以事務(wù)也是不生效的。如果要觸發(fā)默認(rèn) RuntimeException之外異常的回滾,則需要在 @Transactiona事務(wù)注解上指定異常類,示例如下:

@Transactional(rollbackFor = Exception.class)

在今天的文章中總結(jié)了使用 @Transactional注解導(dǎo)致事務(wù)失效的幾個常見場景,如果 @Transactional事務(wù)不生效,則可以根據(jù)這幾種情形排查一下,其實(shí)次數(shù)最多的也就是發(fā)生自身調(diào)用、異常被捕獲、異常拋出類型不匹配這幾種場景。

關(guān)鍵詞:

相關(guān)新聞

Copyright 2015-2020   三好網(wǎng)  版權(quán)所有 聯(lián)系郵箱:435 22 [email protected]  備案號: 京ICP備2022022245號-21