您好,登錄后才能下訂單哦!
這期內(nèi)容當中小編將會給大家?guī)碛嘘P(guān)如何在Spring中使用@Transactional注解,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
@Transactional service A(){ try{ insert(); serviceB.update(); }catch(){ throw new RunTimeException(); } }
serviceB(){ @Transactional update(){ try{ mapperB.update(); }catch(){ throw new RunTimeException(); } } }
mapperB (){ try{ //doSomething.... return true; }catch(){ return false; } }
上面的例子中我的異常出現(xiàn)再//doSomething…的一個sql執(zhí)行異常了,serviceA 中的insert卻一直不能回滾,根本原因在于異常處只返回了false,并沒有拋出運行異常,沒有往上一層拋,serviceB中有拋出運行異常,卻只拿到了一個false,故不會回滾。
下面總結(jié)下常見的事務(wù)不會回滾的集中情況:
1、數(shù)據(jù)庫引擎不支持事務(wù)
這里以 MySQL 為例,其 MyISAM 引擎是不支持事務(wù)操作的,InnoDB 才是支持事務(wù)的引擎,一般要支持事務(wù)都會使用 InnoDB。
2、沒有被 Spring 管理
如下面例子所示:
// @Service public class OrderServiceImpl implements OrderService { @Transactional public void updateOrder(Order order) { // update order } }
如果此時把 @Service 注解注釋掉,這個類就不會被加載成一個 Bean,那這個類就不會被 Spring 管理了,事務(wù)自然就失效了。
3、方法不是 public 的
@Transactional 只能用于 public 的方法上,否則事務(wù)不會失效,如果要用在非 public 方法上,可以開啟 AspectJ 代理模式。
以下來自 Spring 官方文檔:
When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.
也是說的上面那個意思。
4、自身調(diào)用問題
來看兩個示例:
@Service public class OrderServiceImpl implements OrderService { public void update(Order order) { updateOrder(order); } @Transactional public void updateOrder(Order order) { // update order } }
update方法上面沒有加 @Transactional 注解,調(diào)用有 @Transactional 注解的 updateOrder 方法,updateOrder 方法上的事務(wù)管用嗎?
再來看下面這個例子:
@Service public class OrderServiceImpl implements OrderService { @Transactional public void update(Order order) { updateOrder(order); } @Transactional(propagation = Propagation.REQUIRES_NEW) public void updateOrder(Order order) { // update order } }
這次在 update 方法上加了 @Transactional,updateOrder 加了 REQUIRES_NEW 新開啟一個事務(wù),那么新開的事務(wù)管用么?
這兩個例子的答案是:不管用!
因為它們發(fā)生了自身調(diào)用,就調(diào)該類自己的方法,而沒有經(jīng)過 Spring 的代理類,默認只有在外部調(diào)用事務(wù)才會生效,這也是老生常談的經(jīng)典問題了。
5、數(shù)據(jù)源沒有配置事務(wù)管理器
@Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); }
如上面所示,當前數(shù)據(jù)源若沒有配置事務(wù)管理器,那也是白搭!
6、不支持事務(wù)
來看下面這個例子:
@Service public 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: 表示不以事務(wù)運行,當前若存在事務(wù)則掛起,都主動不支持以事務(wù)方式運行了,那事務(wù)生效也是白搭。
7、異常被吃了
這個也是出現(xiàn)比較多的場景:
// @Service public class OrderServiceImpl implements OrderService { @Transactional public void updateOrder(Order order) { try { // update order } catch { } } }
把異常吃了,然后又不拋出來,事務(wù)怎么回滾吧!
8、異常類型錯誤
上面的例子再拋出一個異常:
// @Service public class OrderServiceImpl implements OrderService { @Transactional public void updateOrder(Order order) { try { // update order } catch { throw new Exception("更新錯誤"); } } }
這樣事務(wù)也是不生效的,因為默認回滾的是:RuntimeException,如果你想觸發(fā)其他異常的回滾,需要在注解上配置一下,如:
@Transactional(rollbackFor = Exception.class)
這個配置僅限于 Throwable 異常類及其子類。
上述就是小編為大家分享的如何在Spring中使用@Transactional注解了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。