色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

spring 中事務(wù)注解@Transactional與trycatch的使用

瀏覽:18日期:2023-07-08 11:26:56
spring事務(wù)注解@Transactional與trycatch

在項(xiàng)目中 @service層中 我們會(huì)經(jīng)常在做一些增刪改操作的方法上看到 spring 的事務(wù)注解 @transaction 已知@transaction 是讓spring 幫我們實(shí)現(xiàn)事務(wù)的控制。

但是在項(xiàng)目中會(huì)經(jīng)常看到 有的方法中 會(huì)存在trycatch塊包括的方法上注解著@transaction

eg:

@Override @Transactional public Json addOrder(TOrderAddReq tOrderAddReq) { try{ //增刪改方法} catch (Exception e) { ..... e.printStackTrace();}//}return json; }

上述的方法執(zhí)行后可以看到事務(wù)并沒(méi)有執(zhí)行,接下來(lái)再看一個(gè)例子eg:

@Override @Transactional public Json addOrder(TOrderAddReq tOrderAddReq) { try{ //增刪改方法} catch (Exception e) { // 手動(dòng)硬編碼開(kāi)啟spring事務(wù)管理 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); e.printStackTrace();}//}return json; }

上述方法執(zhí)行后我們可以看到事務(wù)最后執(zhí)行了,但實(shí)際上 事務(wù) 執(zhí)行只是因?yàn)槭謩?dòng)硬編碼開(kāi)啟spring事務(wù)管理起了作用 而方法上的注解并沒(méi)有起作用

接下來(lái)再看一個(gè)例子eg

@Override @Transactional public Json addOrder(TOrderAddReq tOrderAddReq) { try{ //增刪改方法} catch (Exception e) { throw new RuntimeException(); }//}return json; }

上述方法執(zhí)行后我們可以看到事務(wù)是執(zhí)行了的,但這里有個(gè)小細(xì)節(jié):@Transactional不做任何配置 默認(rèn)是對(duì)拋出的unchecked異常回滾,checked異常不會(huì)回滾,為了讓所有異常都會(huì)讓事務(wù)啟動(dòng)可以將 @Transactional配置為 @Transactional(rollbackFor = Exception.class)

解釋:

spring的事務(wù)邊界是在調(diào)用業(yè)務(wù)方法之前開(kāi)始的,業(yè)務(wù)方法執(zhí)行完畢之后來(lái)執(zhí)行commit or rollback(spring默認(rèn)取決于是否拋出runtime異常).

如果拋出runtime exception 并在你的業(yè)務(wù)方法中沒(méi)有catch到的話,事務(wù)會(huì)回滾。

一般不需要在業(yè)務(wù)方法中catch異常,如果非要catch,在做完你想做的工作后(比如關(guān)閉文件等)一定要拋出runtime exception,否則spring會(huì)將你的操作commit,這樣就會(huì)產(chǎn)生臟數(shù)據(jù).所以你的catch代碼是畫(huà)蛇添足。

@Transactional回滾問(wèn)題(try catch、嵌套)

Spring 事務(wù)注解 @Transactional 本來(lái)可以保證原子性,如果事務(wù)內(nèi)有報(bào)錯(cuò)的話,整個(gè)事務(wù)可以保證回滾,但是加上try catch或者事務(wù)嵌套,可能會(huì)導(dǎo)致事務(wù)回滾失敗。測(cè)試一波。

準(zhǔn)備

建兩張表,模擬兩個(gè)數(shù)據(jù)操作

CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, `age` smallint(3) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;CREATE TABLE `role` ( `id` int(11) NOT NULL AUTO_INCREMENT, `role_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;測(cè)試

根據(jù)排列組合原理,我們進(jìn)行四種測(cè)試:1、無(wú)try catch、無(wú)嵌套;2、有try catch、無(wú)嵌套;3、無(wú)try catch、有嵌套;4、都有。

最簡(jiǎn)單測(cè)試

如果我們單純@Transactional,事務(wù)可以正常回滾嗎?

@GetMapping('/saveNormal0') @Transactional public void saveNormal0() throws Exception {int age = random.nextInt(100);User user = new User().setAge(age).setName('name:'+age);userService.save(user);throw new RuntimeException(); }

如果事務(wù)內(nèi)報(bào)了RuntimeException錯(cuò)誤,事務(wù)可以回滾。

@GetMapping('/saveNormal0') @Transactional public void saveNormal0() throws Exception {int age = random.nextInt(100);User user = new User().setAge(age).setName('name:'+age);userService.save(user);throw new Exception(); }

如果事務(wù)內(nèi)報(bào)了Exception錯(cuò)誤(非RuntimeException錯(cuò)誤),事務(wù)不可以回滾。

@GetMapping('/saveNormal0') @Transactional( rollbackFor = Exception.class) public void saveNormal0() throws Exception {int age = random.nextInt(100);User user = new User().setAge(age).setName('name:'+age);userService.save(user);throw new Exception(); }

如果是Exception錯(cuò)誤(非RuntimeException),加上 rollbackFor = Exception.class 參數(shù)也可以實(shí)現(xiàn)回滾。

結(jié)論一:對(duì)于@Transactional可以保證RuntimeException錯(cuò)誤的回滾,如果想保證非RuntimeException錯(cuò)誤的回滾,需要加上rollbackFor = Exception.class 參數(shù)。

try catch 影響

經(jīng)過(guò)博主多種情況測(cè)試,發(fā)現(xiàn)try catch對(duì)回滾這個(gè)事本身沒(méi)有什么影響,結(jié)論一照樣成立。try catch只是對(duì)異常是否可以被@Transactional 感知 到有影響。如果錯(cuò)誤拋到切面可以感知到的地步,那就可以起作用。

@GetMapping('/saveTryCatch') @Transactional( rollbackFor = Exception.class) public void saveTryCatch() throws Exception{try{ int age = random.nextInt(100); User user = new User().setAge(age).setName('name:'+age); userService.save(user); throw new Exception();}catch (Exception e){ throw e;} }

比如上面一段代碼就回滾了。

@GetMapping('/saveTryCatch') @Transactional( rollbackFor = Exception.class) public void saveTryCatch() throws Exception{try{ int age = random.nextInt(100); User user = new User().setAge(age).setName('name:'+age); userService.save(user); throw new Exception();}catch (Exception e){} }

然而,將catch中的錯(cuò)誤不繼續(xù)網(wǎng)上拋,切面無(wú)法感知到錯(cuò)誤,無(wú)法進(jìn)行處理,那么事務(wù)就無(wú)法回滾了。

結(jié)論二:try catch只是對(duì)異常是否可以被@Transactional 感知 到有影響。如果錯(cuò)誤拋到切面可以感知到的地步,那就可以起作用。

事務(wù)嵌套 影響

首先經(jīng)過(guò)實(shí)驗(yàn),結(jié)論一仍然成立,即,當(dāng)不加上rollbackFor = Exception.class 的時(shí)候,無(wú)論內(nèi)外報(bào)RuntimeException,都會(huì)回滾;無(wú)論內(nèi)外報(bào) 非RuntimeException 錯(cuò)誤,都不會(huì)回滾。如果加上rollbackFor = Exception.class,無(wú)論內(nèi)外怎么報(bào)錯(cuò),都會(huì)回滾。這些代碼就不給出了。接下來(lái),試下下面兩種情況:

@GetMapping('/out') @Transactional( rollbackFor = Exception.class) public void out() throws Exception{innerService.inner();int age = random.nextInt(100);User user = new User().setAge(age).setName('name:' + age);userService.save(user);throw new Exception(); } @Transactional public void inner() throws Exception{Role role = new Role();role.setRoleName('roleName:'+new Random().nextInt(100));roleService.save(role);//throw new Exception(); }

情況一,外面事務(wù)加上rollbackFor = Exception.class,里面事務(wù)不加,測(cè)試內(nèi)外分別報(bào)錯(cuò)的情況(為了簡(jiǎn)化代碼量,只給出了外面報(bào)錯(cuò)的代碼),都可以回滾。因?yàn)椋瑹o(wú)論如何,錯(cuò)誤都拋給了外面那個(gè)事務(wù)進(jìn)行處理,而外面那個(gè)加上了rollbackFor = Exception.class,具備處理非RuntimeException錯(cuò)誤的能力,所以都可以讓事務(wù)進(jìn)行正常回滾。

下面看情況二,里面的事務(wù)加上rollbackFor = Exception.class,外面不加,外面報(bào)錯(cuò)。

@GetMapping('/out') @Transactional public void out() throws Exception{innerService.inner();int age = random.nextInt(100);User user = new User().setAge(age).setName('name:' + age);userService.save(user);throw new Exception(); }@Transactional( rollbackFor = Exception.class) public void inner() throws Exception{Role role = new Role();role.setRoleName('roleName:'+new Random().nextInt(100));roleService.save(role); }

事務(wù)都無(wú)法回滾,這是我們有個(gè)疑問(wèn),里面的事務(wù)明明有很強(qiáng)的處理能力啊,為什么和外面一起回滾失敗呢,別著急,等等聊這個(gè)。

然后試下里面報(bào)錯(cuò):

@GetMapping('/out') @Transactional public void out() throws Exception{innerService.inner();int age = random.nextInt(100);User user = new User().setAge(age).setName('name:' + age);userService.save(user); } @Transactional( rollbackFor = Exception.class) public void inner() throws Exception{Role role = new Role();role.setRoleName('roleName:'+new Random().nextInt(100));roleService.save(role);throw new Exception(); }

咦,這回都進(jìn)行了正常的回滾。我的天,這回外面沒(méi)有處理能力,為什么接受里面拋出來(lái)的錯(cuò)誤,也進(jìn)行了回滾!!!看上去,就好像里外事務(wù)總是同生共死的對(duì)不對(duì)?原來(lái),@Transactional還有個(gè)參數(shù),看下源碼,這個(gè)注解還有默認(rèn)值:

Propagation propagation() default Propagation.REQUIRED;

REQUIRED的意思是說(shuō),事務(wù)嵌套的時(shí)候,如果發(fā)現(xiàn)已經(jīng)有事務(wù)存在了,就加入這個(gè)事務(wù),而不是新建一個(gè)事務(wù),所以根本就不存在兩個(gè)事務(wù),一直只有一個(gè)!至于,此參數(shù)其他值,本文不進(jìn)行測(cè)試。回到上面的問(wèn)題,當(dāng)外面報(bào)錯(cuò)的時(shí)候,此時(shí)查看事務(wù),沒(méi)有增加rollbackFor = Exception.class參數(shù),即沒(méi)有處理非RuntimeException能力,所以代碼走完,貌似“兩個(gè)事務(wù)”,都回滾失敗了。當(dāng)里面報(bào)錯(cuò)的時(shí)候,事務(wù)已經(jīng)添加上了處理非RuntimeException能力,所以,代碼走完就回滾成功了。

結(jié)論三:由于REQUIRED屬性,“兩個(gè)事務(wù)”其實(shí)是一個(gè)事務(wù),處理能力看報(bào)錯(cuò)時(shí)刻,是否添加了處理非RuntimeException的能力。

try catch和事務(wù)嵌套 共同影響

在結(jié)論一二三成立的條件下,探索共同影響的問(wèn)題就簡(jiǎn)單多了,由于情況太多,就不進(jìn)行過(guò)多的代碼展示了。

結(jié)論

結(jié)論一:

對(duì)于@Transactional可以保證RuntimeException錯(cuò)誤的回滾,如果想保證非RuntimeException錯(cuò)誤的回滾,需要加上rollbackFor = Exception.class 參數(shù)。

結(jié)論二:

try catch只是對(duì)異常是否可以被@Transactional 感知 到有影響。如果錯(cuò)誤拋到切面可以感知到的地步,那就可以起作用。

結(jié)論三:

由于REQUIRED屬性,“兩個(gè)事務(wù)”其實(shí)是一個(gè)事務(wù),處理能力看報(bào)錯(cuò)時(shí)刻,是否添加了處理非RuntimeException的能力。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 久久精品免费观看 | 国产精品免费视频一区二区三区 | 91久久香蕉青青草原娱乐 | 成年女人毛片免费播放人 | 2022国内精品免费福利视频 | freese×video性欧美丝袜 | 亚洲男人天 | 美女视频一区二区三区 | 99久久免费精品国产免费高清 | chinese耄耋70老太性 | 欧美日韩精品一区二区另类 | 久久91精品国产91久久户 | 一级片图片 | 成人怡红院 | 精品一久久香蕉国产线看观 | 国产男人的天堂 | 亚洲欧美日韩国产综合高清 | 97在线免费视频 | 亚洲精品久一区 | 久久成人福利视频 | 手机看片国产免费 | 特级做a爰片毛片免费看一区 | 九九夜色 | 久久色视频在线观看 | 国产三级网站 | 亚洲成综合 | 午夜男人女人爽爽爽视频 | 美女被免费视频的网站 | 亚洲综合久 | 欧美高清成人 | 曰韩一级毛片 | 亚洲欧美在线观看视频 | 久久精品国产99国产精品亚洲 | 美女视频黄的免费看网站 | 日本aaaa片毛片免费 | 亚洲精品中文字幕一区在线 | 中文字幕精品在线观看 | 久久国产毛片 | 国产成人精品久久亚洲高清不卡 | 日韩在线精品视频 | chinese性老妇中国 |