<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
spring事務是通過動態代理的方法來實現的,有兩種實現動態代理的方式,jdk動態代理方式是將目標物件放入代理物件內部,通過代理物件來存取目標物件;cglib位元組碼生成是通過生成目標物件的子類,通過重寫的方式來完成對父類別的增強。
但是它倆實際上可以為非public方法生成代理物件,只不過spring在呼叫動態代理之前,會過濾掉非public方法。如果修改spring的原始碼就可以為非public方法生成代理物件了。
若同一類中的沒有@Transactional註解的方法內部呼叫有@Transactional註解的方法,那麼該事務會被忽略。
原因是Spring事務是通過Spring AOP完成的,如果從外部直接存取使用@Transactional註解的方法,那麼spring實際上會呼叫代理物件上的方法,在代理物件中完成事務的邏輯;
但是如果從目標物件內部呼叫了使用@Transactional註解的方法,比如在method1方法中呼叫了method2方法,method1沒有加@Transactional 註解,就算method2加了@Transactional 註解也沒用。因為這時會直接呼叫目標物件中的method1方法,進而再呼叫目標物件的method2方法,並沒有走代理物件導致代理失效。
內部捕捉了異常,沒有丟擲新的異常,導致事務操作不會進行回滾:
原因是spring事務原始碼中是通過有沒有出現異常來判斷是否回滾的。
所以最好給@Transactional新增上rollbackFor=Exception.class
錯誤地使用傳播機制也會導致事務失效。如果使用了NOT_SUPPORTED和NEVER傳播機制,那麼事務機會失效,如果使用了SUPPORTS傳播機制並且當前不存在事務那麼事務也會失效。
TransactionDefinition.PROPAGATION_SUPPORTS
: 如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續執行。TransactionDefinition.PROPAGATION_NOT_SUPPORTED
: 以非事務方式執行,如果當前存在事務,則把當前事務掛起。TransactionDefinition.PROPAGATION_NEVER
: 以非事務方式執行,如果當前存在事務,則丟擲異常。環境springboot2.7,mysql5.7
@Component @Order(6) @Slf4j public class TestRunner implements ApplicationRunner { @Autowired TestService testService; @Override public void run(ApplicationArguments args) throws Exception { testService.insertAndUpdate(); } }
@Service("testService") public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements TestService { @Override public boolean updateByIdOne() { LambdaUpdateWrapper<Test> lambdaUpdateWrapper = new UpdateWrapper<Test>().lambda(); lambdaUpdateWrapper.eq(Test::getId,1); lambdaUpdateWrapper.set(Test::getName,"test"); return this.update(lambdaUpdateWrapper); } @Transactional(rollbackFor = RuntimeException.class) @Override public boolean insertAndUpdate() { boolean b = this.updateByIdOne(); Test test = new Test(); test.setName("2222"); boolean save = this.save(test); if(b){ throw new RuntimeException("ts"); } return save; } }
以上程式碼先跑一遍,看看丟擲異常情況,能不能回滾
看庫 毫無變化
看主鍵遞增量其實是插入過了,我覺得事務還是生效了
@Service("testService") public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements TestService { @Transactional(rollbackFor = RuntimeException.class) @Override public boolean updateByIdOne() { LambdaUpdateWrapper<Test> lambdaUpdateWrapper = new UpdateWrapper<Test>().lambda(); lambdaUpdateWrapper.eq(Test::getId,1); lambdaUpdateWrapper.set(Test::getName,"test"); boolean update = this.update(lambdaUpdateWrapper); if(update){ throw new RuntimeException("updateByIdOne"); } LambdaUpdateWrapper<Test> lambdaUpdateWrapper2 = new UpdateWrapper<Test>().lambda(); lambdaUpdateWrapper2.eq(Test::getId,2); lambdaUpdateWrapper2.set(Test::getName,"test"); boolean update1 = this.update(lambdaUpdateWrapper2); return update; } @Transactional(rollbackFor = RuntimeException.class) @Override public boolean insertAndUpdate() { Test test = new Test(); test.setName("2222"); boolean save = this.save(test); boolean b = this.updateByIdOne(); return save; } }
執行結果
子父方法都有事務註解,事務生效
@Service("testService") public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements TestService { @Override public boolean updateByIdOne() { LambdaUpdateWrapper<Test> lambdaUpdateWrapper = new UpdateWrapper<Test>().lambda(); lambdaUpdateWrapper.eq(Test::getId,1); lambdaUpdateWrapper.set(Test::getName,"test"); boolean update = this.update(lambdaUpdateWrapper); if(update){ throw new RuntimeException("updateByIdOne"); } return update; } @Transactional(rollbackFor = RuntimeException.class) @Override public boolean insertAndUpdate() { Test test = new Test(); test.setName("2222"); boolean save = this.save(test); boolean b = this.updateByIdOne(); return b; } }
insertAndUpdate插入成功後又回滾,update 更新成功也回滾,事務生效
@Service("testService") public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements TestService { @Transactional(rollbackFor = RuntimeException.class) @Override public boolean updateByIdOne() { LambdaUpdateWrapper<Test> lambdaUpdateWrapper = new UpdateWrapper<Test>().lambda(); lambdaUpdateWrapper.eq(Test::getId,1); lambdaUpdateWrapper.set(Test::getName,"test"); boolean update = this.update(lambdaUpdateWrapper); if(update){ throw new RuntimeException("updateByIdOne"); } LambdaUpdateWrapper<Test> lambdaUpdateWrapper2 = new UpdateWrapper<Test>().lambda(); lambdaUpdateWrapper2.eq(Test::getId,2); lambdaUpdateWrapper2.set(Test::getName,"test"); boolean update1 = this.update(lambdaUpdateWrapper2); return update; } @Override public boolean insertAndUpdate() { boolean b = this.updateByIdOne(); return b; } }
以上程式碼一跑,結果就很清楚了。
1、在同類中呼叫,二個方法都有加上事務註解,生效
2、同類中,子方法有事務註解,父類別方法無事務註解,在controller層呼叫父類別方法,子方法事務不生效
3、同類中,子方法無事務註解,父類別方法有事務註解,在controller層呼叫父類別方法,之方法事務生效
這些僅為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45