spring的事务传播机制

spring的事务传播机制

嫌弃内容代码复杂的可直接看思维导图大纲即可

基本概念

指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行


(相关资料图)

七种行为和测试PROPAGATION_REQUIRED

默认,当前存在事务,则加入该事务;不存在事务,创建新事务。

public class PropagationService {    @Autowired    private    PropagationMapper propagationMapper;    @Autowired@Lazy    PropagationService propagationService;@Transactional(rollbackFor = Exception.class)    public void insertPropagationA() throws Exception {        Propagation propagationA = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationA").build();        propagationMapper.insert(propagationA);        propagationServiceSelf.insertPropagationB();        throw new Exception();    }    @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.REQUIRED)    public void insertPropagationB() throws Exception {        Propagation propagationB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationB").build();        Propagation propagationBB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationBB").build();        propagationMapper.insert(propagationB);        propagationMapper.insert(prop
@Test    //Given A传播行为required 和B为required,WHE A发生异常,THEN A插入失败,B插入失败    public void testRequired() throws Exception {        propagationService.insertPropagationA();    }
PROPAGATION_REQUIRED_NEW

始终以新的事务运行,当前存在事务,则挂起原事务;不存在事务,创建新事务

@Test    //Given 同样代码更改B为required_new, WHE A发生异常, THEN B插入成功,A插入失败    public void testRequiredNew() throws Exception {        propagationService.insertPropagationA();    }
PROPAGATION_SUPPORTS

支持当前事务。当前存在事务,则支持该事务;不存在事务,以非事务方式执行

@Test    //Given 更改B为required_supports, A不开启事物, WHE B发生异常, THEN A、B插入成功BB失败;A开启事物因为有异常发生全失败    public void testRequiredSupports() throws Exception {        propagationService.insertPropagationA();    }
//@Transactional(rollbackFor = Exception.class)    public void insertPropagationA() throws Exception {        Propagation propagationA = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationA").build();        propagationMapper.insert(propagationA);        propagationServiceSelf.insertPropagationB();        throw new Exception();    }    @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.SUPPORTS)    public void insertPropagationB() throws Exception {        Propagation propagationB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationB").build();        Propagation propagationBB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationBB").build();        propagationMapper.insert(propagationB);        int a =  1/0;        propagationMapper.insert(propagationBB);    }
PROPAGATION_NO_SUPPORTED

非事务方式执行,当前存在事务,则挂起该事务

@Test    //Given 更改B为required_not_supports, A开启事物, WHEN A发生异常, THEN A插入失败、B插入成功    public void testRequiredNotSupports() throws Exception {        propagationService.insertPropagationA();    }
@Transactional(rollbackFor = Exception.class)    public void insertPropagationA() throws Exception {        Propagation propagationA = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationA").build();        propagationMapper.insert(propagationA);        propagationServiceSelf.insertPropagationB();        throw new Exception();    }    @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.NOT_SUPPORTED)    public void insertPropagationB() throws Exception {        Propagation propagationB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationB").build();        Propagation propagationBB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationBB").build();        propagationMapper.insert(propagationB);        propagationMapper.insert(propagationBB);    }
PROPAGATION_NEVER

非事务方式执行,当前存在事务,则抛出异常();

org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation "never"

at org.springframework.transaction.support.AbstractPlatformTransactionManager.handleExistingTransaction(AbstractPlatformTransactionManager.java:413)
@Transactional(rollbackFor = Exception.class)    public void insertPropagationA() throws Exception {        Propagation propagationA = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationA").build();        propagationMapper.insert(propagationA);        propagationServiceSelf.insertPropagationB();        //throw new Exception();    }    @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.NEVER)    public void insertPropagationB() throws Exception {        Propagation propagationB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationB").build();        Propagation propagationBB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationBB").build();        propagationMapper.insert(propagationB);        propagationMapper.insert(propagationBB);    }
@Test    //Given 更改B为required_never, A开启事物, 调用方法B时报错    public void testRequiredNever() throws Exception {        propagationService.insertPropagationA();    }
PROPAGATION_NESTED

当前存在事务,则嵌套在该事务下起新事务执行;不存在事务,创建新事务。

@Test    //Given 更改B为required_nested, A开启事物, 调用方法B,后抛出异常,都失败;A开启事物,调用方法B,B抛出异常,A catch,A成功,B失败    public void testRequiredNested() throws Exception {        propagationService.insertPropagationA();    }
@Transactional(rollbackFor = Exception.class)    public void insertPropagationA() throws Exception {        Propagation propagationA = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationA").build();        propagationMapper.insert(propagationA);        try{            propagationServiceSelf.insertPropagationB();        }catch(Exception e){        }    }    @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.NESTED)    public void insertPropagationB() throws Exception {        Propagation propagationB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationB").build();        Propagation propagationBB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationBB").build();        propagationMapper.insert(propagationB);        int a = 1/0;        propagationMapper.insert(propagationBB);    }
PROPAGATION_MANDATORY

事务方式运行,当前不存在事务,则抛出异常

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation "mandatory"

at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:362)
//@Transactional(rollbackFor = Exception.class)    public void insertPropagationA() throws Exception {        Propagation propagationA = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationA").build();        propagationMapper.insert(propagationA);        propagationServiceSelf.insertPropagationB();    }    @Transactional(rollbackFor = Exception.class,propagation = org.springframework.transaction.annotation.Propagation.MANDATORY)    public void insertPropagationB() throws Exception {        Propagation propagationB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationB").build();        Propagation propagationBB = Propagation.builder()                .type("Propagation.REQUIRED")                .comment("propagationBB").build();        propagationMapper.insert(propagationB);        propagationMapper.insert(propagationBB);    }
@Test    //Given 更改B为required_mandatory, WHEN A不开启事物,调用方法B, THEN调用B抛出异常;    public void testRequiredMandatory() throws Exception {        propagationService.insertPropagationA();    }
Transactional失效

spring的事物是基于AOP代理实现的,也就是说背@Transactional修饰的方法所在类会有一个代理类,通过这个代理类实现的。并且也需要底层数据库支持事物,还需要在同一个库中,多个方法运行调用需要在同一个线程中。基于这情况大概失效场景分为两部分

非代理类方向

数据库引擎不支持索引如MyISAm

数据源未配置事物管理器

数据库分布式部署,需要Seata技术解决

多线程,两个事务方法不在同一个线程

代理类方向

类未交给spring,代理自然无法生成

自身调用,相当于this,代理类未生效

事务方法修饰如非public、final、static修饰导致不能被代理

异常类型错误,声明式事务默认对runtimeException、Error才可以触发回滚

对抛出的异常,catch后处理不当。如吞了异常。

设置了错误的传播行为

标签:

最近更新

spring的事务传播机制
2023-04-24 04:47:08
热门看点:如何淡斑祛斑的小方法_如何补肾壮阳小方法
2023-04-24 01:13:02
读书之美|人民网书香之夜:与梁晓声、刘烨等20余位名人共享书香
2023-04-24 00:10:02
两次美国“银行危机”的比较研究:我们从储贷危机中学到什么?
2023-04-23 23:57:06
世界观点:*ST佳沃:公司加工厂Dumestre年一级加工产能7.15万吨
2023-04-23 22:52:15
春天多吃韭菜也要多吃它,营养极高,1元一斤,包成饺子太香了
2023-04-23 21:04:23
国际民调:“人才红利”已成中国发展强劲动力_消息
2023-04-23 18:45:52
宣武区离婚彩礼纠纷律师怎么收费_讯息
2023-04-23 18:06:23
天天观天下!mbr是什么意思_mbr是什么
2023-04-23 17:28:41
世界动态:基金的交易日是什么时间?基金赎回一般几点到账?
2023-04-23 16:41:06
环球观焦点:沙钢起诉复星产投欲冻南钢11%股权,复星:罔顾事实滥用诉讼权
2023-04-23 16:24:02
新消息丨03月03日铜陵前往邵阳出行防疫政策查询-从铜陵出发到邵阳的防疫政策
2023-04-23 16:06:09
共迎世界读书日,济宁市图书馆《我爱读课文》走进运河书屋
2023-04-23 15:35:08
天天快消息!承德一中录取分数线是多少(承德一中录取分数线)
2023-04-23 15:29:51
焦点日报:向死而生的意思和含义_向死而生的意思
2023-04-23 15:01:12
我国首辆镁合金轻量化挂车在中国西部科技创新港交付-世界速递
2023-04-23 14:26:17
全球速看:探索科学的奥秘,农科院蔬菜花卉研究所举办主题开放日活动
2023-04-23 13:57:07
微头条丨人和路街道逸园社区开展“品味书香”读书分享活动
2023-04-23 13:34:08
资讯:我想给火爆的成都楼市浇点冷水
2023-04-23 13:14:49
4月23日山东地区氢氟酸市场价格暂稳
2023-04-23 13:16:02
南通通州区入学报名南通州APP下载方式+入口(2023年)
2023-04-23 12:34:09
环球视点!计算机辅助教学软件c ai_计算机辅助教学软件_CAI是啥
2023-04-23 12:01:53
新闻周刊丨多地学校向市民开放体育场地 家旁操场让健身更方便!_世界视点
2023-04-23 11:43:06
全球新资讯:驾照实习期到了要换证不 驾照实习期到了要换证
2023-04-23 11:18:15
Skip:三分排联盟27的热火上半场进了12个三分 他们是东部威少
2023-04-23 11:01:00
三月三上巳节 游春踏青诵经典
2023-04-23 10:24:04
今日时讯:皮尔斯勇士的冠军窗口已关闭 皮尔斯不同意吹杨被高估他首次打季后赛很惊艳他设立了高标准 当前看点
2023-04-23 10:22:24
市商务局开展“五一”节前重点行业督导_世界短讯
2023-04-23 09:49:09
焦点滚动:甚的部首是什么部首-甚的部首
2023-04-23 09:34:58
海南琼中黎苗同胞欢庆传统节日“三月三”_每日速递
2023-04-23 09:11:59