Spring事务传播属性

参考文献

Spring事务传播属性和隔离级别 https://www.cnblogs.com/eunice-sun/p/11024584.html

spring事务传播机制总结 https://blog.csdn.net/m18330808841/article/details/109543815

spring boot @Transactional注解事务不回滚不起作用无效 https://blog.csdn.net/zdyueguanyun/article/details/80236401?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

正文

扫盲示例

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo-order</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo-order</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.26</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

application.properties

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=root

App.java

package com.example.demoorder;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

UserController.java

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @Autowired
    private ServiceA serviceA;

    @GetMapping("/a")
    public void a() {
        serviceA.methodA();
    }
}

UserService.java

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {
    @Autowired
    private UserMapper mapper;

    //什么都不写时,默认为Propagation.REQUIRED
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        int i = 1 / 0;
    }

    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
    }
}

UserMapper.java

package com.example.demoorder;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface UserMapper {
    @Insert("insert into a (id,name) values (#{id},#{name})")
    public void saveA(@Param("id") Integer id, @Param("name") String name);

    @Insert("insert into b (id,name) values (#{id},#{name})")
    public void saveB(@Param("id") Integer id, @Param("name") String name);
}

ServiceA.java

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    //@Autowired
    //private ServiceB serviceB;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        //serviceB.methodB();
        int i = 1 / 0;
    }
}

ServiceB.java

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
    }
}

测试:浏览器输入 127.0.0.1:8080/a 

a表回滚成功

示例1

Propagation.REQUIRED
1.如果前面的方法已经创建了事务,那么后面的方法加入这个已存在的事务

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a和b表都回滚成功。

2.如果前面的方法没有创建事务,那么后面的方法会新建一个事务.

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现b表回滚成功,但是a表没有回滚。

示例2:Propagation.SUPPORTS
1如果当前存在事务,则加入当前事务

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a和b表都回滚成功。
2如果当前没有事务,就以非事务方法执行

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a和b表都不回滚。

示例3:Propagation.MANDATORY
1当前存在事务,则加入当前事务,

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        methodB();
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a和b表都回滚成功。
2如果当前事务不存在,则抛出异常。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.MANDATORY)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a表不回滚,methodB()方法进不来,也不打印methodB字符串。

示例4 : Propagation.REQUIRES_NEW

在执行时,不论当前是否存在事务,总是会新建一个事务。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
        int i = 1 / 0;
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");

    }
}

测试:调用methodA()方法,发现a表回滚,b表插入数据库成功,b表不回滚

示例5 :Propagation.NOT_SUPPORTED

在执行时,不论当前是否存在事务,都会以非事务的方式运行。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a表回滚,b表不回滚

示例6 :Propagation.NEVER

就是我这个方法不使用事务,并且调用我的方法也不允许有事务,如果调用我的方法有事务则我直接抛出异常。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.NEVER)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a表回滚,ServiceB的methodB不执行,不打印methodB字符串

示例7 :Propagation.NESTED

如果当前事务不存在,则像 Propagation.REQUIRED开启一个新事物
如果当前事务存在,则在嵌套事务中执行。嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;

    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.NESTED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a表不回滚,b表回滚

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        try {
            serviceB.methodB();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.NESTED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
        int i = 1 / 0;
    }
}

测试:调用methodA()方法,发现a表不回滚,b表回。因为调用方catch了被调方的异常,所以只有子事务回滚了。

package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceA {
    @Autowired
    private UserMapper mapper;
    @Autowired
    private ServiceB serviceB;
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        System.out.println("methodA");
        mapper.saveA(11, "aa");
        serviceB.methodB();
        int i = 1 / 0;
    }
}
package com.example.demoorder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class ServiceB {
    @Autowired
    private UserMapper mapper;

    @Transactional(propagation = Propagation.NESTED)
    public void methodB() {
        System.out.println("methodB");
        mapper.saveB(22, "bb");
    }
}

测试:调用methodA()方法,发现a表回滚,b表回滚
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cgm625637391

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值