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后处理不当。如吞了异常。

设置了错误的传播行为

标签:

最近更新

天天视讯!央行调查:未来三个月16.2%居民打算购房,比例大幅回落
2023-07-03 16:17:50
滚动:宝沃注销生产资质引热议 小米汽车面临双重考验?
2023-07-03 16:00:06
中华经典诵读大会海选作品《纸船》 环球短讯
2023-07-03 15:33:24
魔兽世界进阶畜牧业_进阶畜牧业 环球头条
2023-07-03 15:15:26
东北铁路列车运行框架全面优化 实现“进京”高铁“公交化”
2023-07-03 14:40:56
耐克2023财年营收为512亿美元,大中华区连续三季度正增长 通讯
2023-07-03 13:57:58
消息指众安智慧生活国际配售部分已获足额认购
2023-07-03 13:32:21
上市!连连数字向港交所递交招股书 今日讯
2023-07-03 12:54:52
华晨中国0.44%股权拍卖以底价1.58亿元成交 焦点
2023-07-03 12:10:27
2023 TCL全球生态合作伙伴大会亮点前瞻:即将官宣碳中和行动计划
2023-07-03 11:56:12
天天快看:新调整的“三有野生动物名录”公布
2023-07-03 11:25:33
实时焦点:暴雨蓝色预警:11省区市将现大到暴雨 江苏四川等局地有大暴雨
2023-07-03 10:55:07
来山西地质博物馆领略大美山西吧|世界即时看
2023-07-03 10:55:55
《火影忍者:终极风暴羁绊》发布原创剧情模式预告-焦点速读
2023-07-03 10:08:46
滑雪气垫大跳台 四川选手夺冠-环球热讯
2023-07-03 09:52:31
济南3日下午起雷雨先行,后半夜全市中雨局地大雨 当前看点
2023-07-03 09:28:16
阿斯巴甜安全性受质疑 更全面审查尚在进行中
2023-07-03 08:55:30
“木头姐”在特斯拉公布交付数据前又抛售近1900万美元股票
2023-07-03 08:34:04
可变身迷你房车 斯柯达Roadiaq官图|焦点播报
2023-07-03 07:54:59
快播:pocketBook电纸书阅读器怎么样?自已看内幕,好坏判断有诀窍
2023-07-03 06:51:18
环球聚焦:家用电脑挖矿一天收益(家用电脑挖矿)
2023-07-03 05:52:39
国内首台无人智慧加油通航服务站在上海投放使用
2023-07-03 03:59:54
环球热讯:台军叫嚣解放军敢越线就开火,话音刚落,大量解放军军机出动
2023-07-03 01:04:09
张震岳好听的十首歌_张震岳的10大经典歌曲
2023-07-02 22:49:13
事关公积金、跨省通办,湖南本周提醒来了!
2023-07-02 21:40:34
通讯!四川:预计川东多条河流将发生接近或超过警戒水位洪水
2023-07-02 20:40:08
【时快讯】给群众吃“定心丸”!政策兜底 分类分级收购受损小麦
2023-07-02 19:54:07
每日速读!祝福香港如紫荆花般绽放
2023-07-02 18:33:05
如何平息骚乱?马克龙的能力和决心受到考验
2023-07-02 17:44:06
探索瞬息万变的东南亚投资与并购版图|ORIGIN大会
2023-07-02 16:56:21