今天不爽-浅谈Spring Transaction

1. 数据库的四个隔离级别

脏读 读取了未提交的数据
不可重复读 发生在修改 同样的条件 读取的值是不一样的
幻读 发生在新增删除 同样的条件 读取出来的数量是不一样的

1.1. read_uncommit 读未提交 可能发生脏读 不可重复读 幻读
1.2 read_commit 读提交 避免脏读 但还是会发生不可重复读 幻读
1.3 repeatable_read 对同一字段多次去读是一致的 但还是会发生幻读 (默认的隔离级别)default
1.4 serializable 最高的隔离级别

2. 事务四个特性

2.1 原子性 事务不可分割
2.2 一致性 执行前后数据一致
2.3 隔离性 执行期间不被其他事务干扰
2.4 持久性 执行完毕后 数据应被持久话到数据库

3. 事务的七个传播行为

3.1 required 如果当前没有事务就新建一个事务 如果有则加入到当前事务
3.2 supports 支持当前事务 如果没有 就以非事务执行
3.3 mandatory 使用当前事务 如果没有抛出异常
3.4 requires_new 新建事务 如果存在事务 则挂起
3.5 not_sopported 以非事务执行 如果存在事务 挂起
3.6 never 如果当前存在事务 抛异常
3.7 nested 如果存在 则在嵌套事务内执行 没有则新建

4. EnableTransactionManagement注解

4.1 首先导入spring-tx jar包

<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.1</version>
</dependency>

4.2 这个注解 @Import了TransactionManagementConfigurationSelector,我们也发现了AdviceMode的mode为 AdviceMode.PROXY

@Target({
    
    ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({
    
    TransactionManagementConfigurationSelector.class})
public @interface EnableTransactionManagement {
    
    
    boolean proxyTargetClass() default false;

    AdviceMode mode() default AdviceMode.PROXY;

    int order() default 2147483647;
}

4.3 selectImports方法,进到case Proxy下,我们发现两个类AutoProxyRegistrar和ProxyTransactionManagementConfiguration

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
    
    

	@Override
	protected String[] selectImports(AdviceMode adviceMode) {
    
    
		switch (adviceMode) {
    
    
			case PROXY:
				return new String[] {
    
    AutoProxyRegistrar.class.getName(),
						ProxyTransactionManagementConfiguration.class.getName()};
			case ASPECTJ:
				return new String[] {
    
    determineTransactionAspectClass()};
			default:
				return null;
		}
	}
}

4.4 先看AutoProxyRegistrar这个类的registerBeanDefinitions方法,最终注册了InfrastructureAdvisorAutoProxyCreator,继承了AbstractAdvisorAutoProxyCreator,所以这个类的主要作用就是开启自动代理的作用

if (mode == AdviceMode.PROXY) {
    
    
	AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
	if ((Boolean) proxyTargetClass) {
    
    
		AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		return;
	}
}

4.5 ProxyTransactionManagementConfiguration

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    
    

	// 一个Pointcut 切入点 根据transactionAttributeSource传入attr属性 进行切入
	//Advisor上一篇文章介绍过 Advisor包含了Advice切面逻辑以及Pointcut切入点
	@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
			TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
    
    

		BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
		advisor.setTransactionAttributeSource(transactionAttributeSource);
		advisor.setAdvice(transactionInterceptor);
		if (this.enableTx != null) {
    
    
			advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
		}
		return advisor;
	}

	// 这个Bean 解析@Transaction里面的属性 no public不起作用
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionAttributeSource transactionAttributeSource() {
    
    
		return new AnnotationTransactionAttributeSource();
	}

	// 事务拦截器 保存了@Transaction的属性信息
	@Bean
	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
	public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
    
    
		TransactionInterceptor interceptor = new TransactionInterceptor();
		interceptor.setTransactionAttributeSource(transactionAttributeSource);
		if (this.txManager != null) {
    
    
			interceptor.setTransactionManager(this.txManager);
		}
		return interceptor;
	}

}

4.6 @Transaction中的各个参数

protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
    
    
	RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();

	Propagation propagation = attributes.getEnum("propagation");
	rbta.setPropagationBehavior(propagation.value());
	Isolation isolation = attributes.getEnum("isolation");
	rbta.setIsolationLevel(isolation.value());

	rbta.setTimeout(attributes.getNumber("timeout").intValue());
	String timeoutString = attributes.getString("timeoutString");
	Assert.isTrue(!StringUtils.hasText(timeoutString) || rbta.getTimeout() < 0,
			"Specify 'timeout' or 'timeoutString', not both");
	rbta.setTimeoutString(timeoutString);

	rbta.setReadOnly(attributes.getBoolean("readOnly"));
	rbta.setQualifier(attributes.getString("value"));
	rbta.setLabels(Arrays.asList(attributes.getStringArray("label")));

	List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
	for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
    
    
		rollbackRules.add(new RollbackRuleAttribute(rbRule));
	}
	for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
    
    
		rollbackRules.add(new RollbackRuleAttribute(rbRule));
	}
	for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
    
    
		rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
	}
	for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
    
    
		rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
	}
	rbta.setRollbackRules(rollbackRules);

	return rbta;
}

5. 举三个例子 事务传播(REQUIRED,REQUIRES_NEW,NESTED)

5.1 REQUIRED

Class A() {
	// 默认就是REQUIRED
	@Transaction
	public void insertA() {
		.......
	}
	
	@Transaction(propagation = Propagation.REQUIRED)
	public void insertB() {
		.......
	}
}
  1. BEGIN;
  2. insert into a(field1, field2) values(1, 2);
  3. insert into b(field1, field2) values(1, 2);// 加入到当前事务
  4. COMMIT or ROLLEBACK;

5.2 REQUIRES_NEW

Class A() {
	// 默认就是REQUIRED
	@Transaction
	public void insertA() {
		.......
	}
	
	@Transaction(propagation = Propagation.REQUIRES_NEW)
	public void insertB() {
		.......
	}
}
  1. BEGIN;

  2. insert into a(field1, field2) values(1, 2);

  3. A方法挂起

  4. BEGIN;// B方法的插入逻辑

  5. insert into b(field1, field2) values(1, 2);

  6. COMMIT OR ROLLEBACK;// 这里的rollback 不影响insertA逻辑 事务的隔离特性

  7. 拿到挂起的数据

  8. COMMIT or ROLLEBACK;

5.3 NESTED

Class A() {
	// 默认就是REQUIRED
	@Transaction
	public void insertA() {
		.......
	}
	
	@Transaction(propagation = Propagation.NESTED)
	public void insertB() {
		.......
	}
}
  1. BEGIN;
  2. insert into a(field1, field2) values(1, 2);
  3. SAVEPOINT xxxx;// 创建SAVEPOINT点 删除保存点 RELEASE SAVEPOINT xxxx;
  4. insert into b(field1, field2) values(1, 2);// 如果这个插入异常
  5. ROLLBACK to xxxx; // 那么insert a操作仍不受影响
  6. COMMIT;// 事务提交 insert a操作正常

NESTED相比于REQUIRES_NEW 少创建一次连接

猜你喜欢

转载自blog.csdn.net/weixin_45657738/article/details/109671006