首页 > 其他分享 >Spring自学日志03-事务

Spring自学日志03-事务

时间:2022-12-06 09:14:41浏览次数:62  
标签:03 事务 对象 Spring Transactional PROPAGATION methodA 日志

目录

一、事务的基本概念

1.1、事务的ACID属性

提到事务,不可避免需要涉及到事务的ACID属性:

  • 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
  • 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
  • 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
  • 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。

我们将严格遵循ACID属性的事务称为刚性事务。与之相对,期望最终一致性,在事务执行的中间状态允许暂时不遵循ACID属性的事务称为柔性事务,可参考传统事务与柔性事务,柔性事务的使用涉及到分布式事务方案,可以后续扩展,这里我们先将注意集中在事务实现原理上。

1.2、事务的隔离级别

根据SQL92标准,MySQL的InnoDB引擎提供四种隔离级别(即ACID中的I):

  1. 读未提交(READ UNCOMMITTED)
  2. 读已提交(READ COMMITTED)
  3. 可重复读(REPEATABLE READ)
  4. 串行化(SERIALIZABLE)

InnoDB默认的隔离级别是REPEATABLE READ,其可避免脏读不可重复读,但不能避免幻读,需要指出的是,InnoDB引擎的多版本并发控制机制(MVCC)并没有完全避免幻读,关于该问题以及隔离级别说明,可参考MySQL的InnoDB的幻读问题

1.3、事务的传播机制

Spring针对方法嵌套调用时事务的创建行为定义了七种事务传播机制,分别是

  1. PROPAGATION_REQUIRED,如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置,也是Spring事务默认的传播机制
  2. PROPAGATION_REQUIRES_NEW,创建一个新事务,如果存在当前事务,则挂起该事务
  3. PROPAGATION_SUPPORT,当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行
  4. PROPAGATION_NOT_SUPPORTED,始终以非事务方式执行,如果当前存在事务,则挂起当前事务
  5. PROPAGATION_MANDATORY,当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常
  6. PROPAGATION_NEVER,不使用事务,如果当前事务存在,则抛出异常
  7. PROPAGATION_NESTED,如果当前事务存在,则在嵌套事务中执行,否则REQUIRED的操作一样(开启一个事务)

基本上从字面意思就能知道每种传播机制各自的行为表现,Spring默认的事务传播机制是PROPAGATION_REQUIRED,即如果当前存在事务,则使用当前事务,否则创建新的事务。

1.4、通过注解开启事务

在 Spring 项目中,我们可以直接使用注解 @Transactional 来标识一个类或方法支持事务。

//可以在类上
@Service
@Transactional
public class Target implements IUserService {
   ............
}


//也可以在类的方法上
@Service
public class Target implements IUserService {
    @Override
    @Transactional
    public void Transaction(UserEntity entity1, UserEntity entity2) {
		.........
    }
}


该注解建议在类上加在方法上加会有隐患,一个没有加@Transactional(MothodA)注解的方法,去调用一个加了@Transactional的方法(MothodB),不会产生事务

public class Target {
    //没有加@Transactional(MothodA)
    public void MothodA(UserEntity entity1, UserEntity entity2) {
        MothodB(entity1, entity2);
    }
    
    //加了@Transactional的方法(MothodB)
    @Transactional
    public void MothodB(UserEntity entity1, UserEntity entity2) {
		.........
    }
}

要知道原因首先了解@Transactional的原理。调用@Transactional方法,如何产生事务?

其实Spring的@Transactional,跟Spring AOP一样,都是利用了动态代理。

我们写了一个类,里面写了一个加了@Transactional注解的方法,这原本平淡无奇,什么用也没有,就像这样:

img

关键在于,Spring在检查到@Transactional注解之后,给这个对象生成了一个代理对象proxy:

img

代理对象的methodB,会先开启事务(beginTransaction),然后再去执行原先对象target的methodB,如果抛异常,则回滚(rollBack),如果一切顺利,则提交(commit)。

而最后注入Spring容器的,也正是这个带有事务逻辑的代理对象。所以我们调用methodB时会产生事务。

现在,我们写了一个新方法,methodA,里头去调用methodB:

img

从上面的分析,可以知道,我们最终拿到的,是代理对象。

那么代理对象的methodA是长什么样子的呢?长这样:

img

由于methodA没有加@Transactional注解,所以代理对象里面,直接就是target.methodA(),直接调用了原来对象的methodA。

这下就很清晰了,代理对象的methodA,去调用原来对象的methodA,原来对象的methodA,再去调用原来对象的methodB,而原来对象的methodB,是不具有事务的。事务只存在于代理对象的methodB. 所以整个方法也就没有事务了。

标签:03,事务,对象,Spring,Transactional,PROPAGATION,methodA,日志
From: https://www.cnblogs.com/csmCode/p/16954211.html

相关文章

  • 使用 aop + guava 为 springboot 应用做限流
    1.引入guava依赖<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId></dependency>编写......
  • mysql基础问题三问(底层逻辑;正在执行;日志观察)
    背景:经常面试会遇到且实际工作中也会应用到的三个场景:目录:一.mysql查询时的底层原理是什么?二.如何查看正在执行的mysql语句?三.如何观察mysql运行过程中的日志信息?--......
  • SpringAMQP
    SpringAMQP是基于RabbitMQ封装的一套模板,并且还利用SpringBoot对其实现了自动装配,使用起来非常方便。SpringAmqp的官方地址:https://spring.io/projects/spring-amqp S......
  • 【Git】The Requested URL return error 403
    问题描述git执行push命令时提示:TheRequestedURLreturnerror403问题分析权限不够,仓库在创建后重装过电脑,管理员不同解决办法删库重开......
  • 日志-2022-12
    1,青蛙......
  • 情绪日志-2022-12
    情绪......
  • Spring源码-03-容器创建
    Spring源码-03-容器创建注解Bean方式publicclassAnnotationCtxMain02{ publicstaticvoidmain(String[]args){ newAnnotationConfigApplicationContext(MyCf......
  • Spring源码-02-Bean容器
    Spring源码-02-Bean容器一类关系二宏观视角......
  • Spring源码-04-注解Bean读取器
    Spring源码-04-注解Bean读取器AnnotatedBeanDefinitionReader一构造方法publicAnnotatedBeanDefinitionReader(BeanDefinitionRegistryregistry,Environmentenviro......
  • Spring依赖注入的方式
    Spring依赖注入有两种类型:setter注入,和构造器注入。setter注入中有简单类型的注入和引用类型的注入,构造器注入也是分这两个类型。setter注入简单类型(直接类型):就是在<prop......