spring的事务传播机制

科技资讯 投稿 7800 0 评论

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

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

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

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

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,代理自然无法生成

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

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

  • 设置了错误的传播行为

编程笔记 » spring的事务传播机制

赞同 (34) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽