Spring-tx-Propagation枚举类

该枚举类定义了spring事务的几种传播行为

传播行为:当一个带有事务的方法A被另外一个方法N调用的时候,A应该如何处理事务?有下面几种处理方式,这些处理方式,就叫做传播行为

  1. NESTED传播行为:如果N不在事务内,则A会创建一个事务,如果N在事务内,则A会在N的事物内,创建一个N的子事务,这个子事务回滚,只会回滚自己,而不会将外层的父事务(N的事务)也回滚,但是如果外N回滚,那么A也会跟着回滚(子可以独立回滚,父如果回滚会带着子回滚)
  2. REQUIRES_NEW传播行为:外层异常,外层回滚,内层不回滚,剩下的和NESTED一样
  3. REQUIRED传播行为:这是spring默认的传播行为,也是我们编码中最最最常用的传播行为,如果N不在事务内,则A会创建一个事务,如果N在事务内,则A直接使用N的事务
  4. NEVER传播行为:A执行的时候,N不允许在事务内,如果N在事物内,直接报错

下面是一些示例代码
由于我测试代码在spring boot中测试的,所以为了方便数据源我使用了Hikar数据源

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

第一个是主函数类,代码如下

@Configuration
@EnableTransactionManagement
public class TestMain {

	@Bean
	public DataSource dataSource() {
		HikariDataSource ds = new HikariDataSource();
		ds.setJdbcUrl("jdbc:mysql://localhost:3306/swttest?serverTimezone=UTC&&useSSL=false");
		ds.setUsername("root");
		ds.setPassword("Aa111111!");
		return ds;
	}

	@Bean
	public JdbcTemplate jdbcTemplate() {
		JdbcTemplate jdbc = new JdbcTemplate();
		jdbc.setDataSource(dataSource());
		return jdbc;
	}

	@Bean
	public PlatformTransactionManager platformTransactionManager() {
		DataSourceTransactionManager manager = new DataSourceTransactionManager(dataSource());
		return manager;
	}

	public static void main(String[] args) throws Throwable {
		// 依赖容器的话必须要开启@EnableTransactionManagement注解,表示告诉spring我要使用事务
		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
				"TestMain所在的包名");
		Creater1 tt = ctx.getBean(Creater1.class);
		tt.create();
	}

第二个是事务类1(类名叫Creater1)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
public class Creater1 {
	@Autowired
	JdbcTemplate jdbcTemplate;
	@Autowired
	Creater2 creater2;

	@Transactional(rollbackFor = Exception.class)
	public void create() {
		jdbcTemplate.update("insert into t1(value) values ('create1')");
		creater2.create();
	}
}

第三个是事务类2

@Component
public class Creater2 {
	@Autowired
	JdbcTemplate jdbcTemplate;

	@Transactional(rollbackFor = Exception.class)
	public void create() {
		jdbcTemplate.update("insert into t1(value) values ('create2')");
	}
}

接下来我将通过修改事务类2(Creater2)来演示不同的传播行为

1.NEVER
表示创建执行的时候,不允许存在其他事务,否则报错,将Creater2做如下修改

@Transactional(rollbackFor = Exception.class)
改为
@Transactional(rollbackFor = Exception.class, propagation = Propagation.NEVER)

运行TestMain,会发现系统报错

2.REQUIRED
默认的模式,不多阐述

3.NESTED
内层事务报错回滚,不会影响到外层事务正常提交,但是要注意只有外部事务结束后它才会被提交,或者回滚,所以写法要注意
1)外层事务应该try住,确保外层事务执行完毕,否则内层事务报错,会抛出来,导致外层也报错
2)不需要设置额外的savepoint,内部事务会自动回滚到事务开始处
Creater1做如下修改

jdbcTemplate.update("insert into t1(value) values ('create1')");
creater2.create();
-------------改为-------------
try {
	jdbcTemplate.update("insert into t1(value) values ('create1')");
	creater2.create();
} catch (Exception e) {

}

Creater2代码变成下面这样

@Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED)
public void create() {
	jdbcTemplate.update("insert into t1(value) values ('create2')");
	throw new RuntimeException("MYS");//手动抛异常
}

运行TestMain,会发现create1插入到数据库,而create2没有入库
日记:NESTED行为下,外层报错,会连同内层一起回滚,但是本文没有演示这种情况
4.REQUIRES_NEW
Creater1代码变成下面这样

@Transactional(rollbackFor = Exception.class)
public void create() {
	jdbcTemplate.update("insert into t1(value) values ('create1')");
	creater2.create();
	throw new RuntimeException("MYS");
}

Creater2代码变成下面这样

@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void create() {
	jdbcTemplate.update("insert into t1(value) values ('create2')");
}

运行TestMain,会发现create2插入到数据库,而create1没有入库

日记:与NESTED的区别及共同点
内层事务如果是NESTED:外层异常,内外两层都回滚
内层事务如果是REQUIRES_NEW:外层异常,外层回滚,内层不回滚
共同点:内层异常,外层try住之后,内层回滚,外层不回滚

还有另外三种传播行为,但是实在是没有必要再去阐述,因为相对来说较为简单,理解了上面四种,另外三种甚至连测试都不需要,脑补就可以

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值