15 声明式事务七种传播行为的表现形式案例

本文深入探讨了Spring声明式事务中的七种传播行为:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER和NESTED。通过代码案例展示了各种传播行为在不同场景下的事务处理方式,例如当外围方法开启或未开启事务时,内部方法的事务如何传播。详细分析了每种传播行为的特点和适用场景。
摘要由CSDN通过智能技术生成

由于md文档部分hugo插件语法不兼容,建议访问作者网站查阅文章:wlizhi.cc

spring源码系列文章,示例代码的中文注释,均是 copy 自 https://gitee.com/wlizhi/spring-framework

链接中源码是作者从 github 下载,并以自身理解对核心流程及主要节点做了详细的中文注释。


1 基础概念

spring声明式事务的传播行为,严格来说是spring特有的,数据库本身并没有这个概念。本文会列举出spring事务的七种传播行为,并以代码案例的方式展示不同的传播行为的表现是怎样的。

1.1 什么是事务传播行为

事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法时事务如何传播。

伪代码:

public class A{
   
    @AutoWired
    private B b;

    public void a(){
   
        b.b();
        // 业务代码...
    } 
}

public class B{
    
    @AutoWired
    private A a;

    @Transaction(Propagation=XXX)
    public void b(){
   
        // 业务代码...
    } 
}

上面代码中 a() 嵌套了 b() 。b() 的事务传播行为由 @Transaction(Propagation=XXX) 决定。注意,a() 并没有开启事务。某一个事务传播行为修饰的方法并不是必须要在开启事务的外围方法中调用。

1.2 spring声明式事务中七种传播行为

传播类型 说明
REQUIRED 如果当前没有事务,就新建一个事务;如果当前存在事务,就加入到当前事务。
SUPPORTS 如果当前没有事务,就以非事务方式运行;如果当前存在事务,就加入到当前事务。
MANDATORY 如果当前没有事务,就抛出异常;如果当前存在事务,就加入到当前事务。
REQUIRES_NEW 总是在新建事务中运行。如果当前已存在事务,就挂起当前事务。
NOT_SUPPORTED 以非事务方式运行;如果当前存在事务,挂起当前事务。
NEVER 以非事务的方式运行。如果当前存在事务,就抛出异常。
NESTED 如果当前存在事务,则在嵌套事务内运行;如果当前不存在事务,则新建一个事务(这时与 REQUIRED 类似)。

2 基础代码准备

文中代码以 Service 和 Dao 两层展示。使用测试用例调用 Service 的方式,框架采用 spring + mybatis ,数据库 mysql。dao 层及实体类代码使用插件生成。

自动代理激活及扫描包配置类 AspectAnoForTransactionConfiguration :

@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {
   "top.wlz922.service"})
public class AspectAnoForTransactionConfiguration {
   

}

事务配置类:

@Configuration
@MapperScan(basePackages = "top.wlz922.dao")
@EnableTransactionManagement
public class GlobalTransactionConfig {
   
	@Autowired
	ApplicationContext context;


	@Bean
	public DataSourceTransactionManager getTransactionManager(@Autowired DataSource ds){
   
		DataSourceTransactionManager manager = new DataSourceTransactionManager();
		manager.setDataSource(ds);
		return manager;
	}

	@Bean
	public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource ds) throws IOException {
   
		SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
		fb.setDataSource(ds);
		ResourcePatternResolver resolver = ResourcePatternUtils.getResourcePatternResolver(context);
		Resource[] resources = resolver.getResources("classpath:sqlmaps/*.xml");
		fb.setMapperLocations(resources);
		return fb;
	}

	@Bean
	public DruidDataSource getDruidDataSource(){
   
		DruidDataSource ds = new DruidDataSource();
		ds.setUsername("root");
		ds.setPassword("123456");
		ds.setUrl("jdbc:mysql://127.0.0.1:3306/test?serverTimezone=Asia/Shanghai");
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		return ds;
	}
}

实体类 PropagationUser :

@Data
@NoArgsConstructor
public class PropagationUser implements Serializable {
   
    private Long id;
    private String name;
    private static final long serialVersionUID = 1L;
    public PropagationUser(String name) {
   
        this.name = name;
    }
}

PropagationUserService (其实现类的事务注解配置与方法名一致):

public interface PropagationUserService {
   
	void addRequired(PropagationUser user);

	void addRequiredException(PropagationUser user);

	void addRequiredNew(PropagationUser user);

	void addRequiredNewException(PropagationUser user);

	void addSupports(PropagationUser user);

	void addSupportsException(PropagationUser user);

	void addNotSupported(PropagationUser user);

	void addNotSupportedException(PropagationUser user);

	void addMadatory(PropagationUser user);

	void addMadatoryException(PropagationUser user);

	void addNever(PropagationUser user);

	void addNeverException(PropagationUser user);

	void addNestead(PropagationUser user);

	void addNesteadException(PropagationUser user);
}

PropagationUserDao :

public interface PropagationUserDao {
   
    int insertSelective(PropagationUser record);
    // 省略...
}

测试类:

public class TransactionPropagationServiceTest {
   
	private TransactionPropagationService service;
	@Before
	public void before() {
   
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
				GlobalTransactionConfig.class, AspectAnoForTransactionConfiguration.class);
		service = context.getBean(TransactionPropagationService.
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值