Spring AOP中的事务处理

Spring 中事务简介

事务定义

事务(Transaction)是一个业务,是一个不可分割的逻辑工作单元,基于事务可以更好的保证业务的正确性。

事务特性

事务具备ACID特性,分别是:

  • 原子性(Atomicity):一个事务中的多个操作要么都成功要么都失败。
  • 一致性(Consistency): 例如存钱操作,存之前和存之后的总钱数应该是一致的。
  • 隔离性(Isolation):事务与事务应该是相互隔离的。
  • 持久性(Durability):事务一旦提交,数据要持久保存。

说明:目前市场上在事务一致性方面,通常会做一定的优化,比方说只要最终一致就可以了,这样的事务我们通常会称之为柔性事务(只要最终一致就可以了).

数据库隔离级别

事务隔离级别共四种,隔离的程度由低至高就是:

隔离级别 隔离级别的值 导致的问题
Read-Uncommitted 0 (读取未提交内容) 导致脏读
Read-Committed 1(读取提交内容) 避免脏读,允许不可重复读和幻读
Repeatable-Read 2(可重读) 避免脏读,不可重复读,允许幻读
Serializable 3 (串行化) 串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读。执行效率慢,使用时慎重

大多数的数据库系统的默认事务隔离级别都是:Read committed(读已提交)
而MySQL的默认事务隔离级别是:Repeatable Read(读未提交)
我们可以采用下面这种方法查询Mysql中的当前事务隔离级别:

SELECT @@tx_isolation

然后使用命令:

SET session TRANSACTION ISOLATION LEVEL Serializable;

(参数可以为:Read uncommitted,Read committed,Repeatable,Serializable)
将MySQL中的事务隔离级别改变成:Serializable,范围是当前session,即一个cmd窗口的范围。

Spring中的隔离级别

常量 解释
ISOLATION_DEFAULT 这是个 PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与 JDBC 的隔离级别相对应。
ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。

Spring 中事务管理

Spring 中事务方式概述

  • Spring框架中提供了一种声明式事务的处理方式,此方式基于AOP代理,可以将具体业务逻辑与事务处理进行解耦。也就是让我们的业务代码逻辑不受污染或少量污染,就可以实现事务控制。
  • 在SpringBoot项目中,其内部提供了事务的自动配置,当我们在项目中添加了指定依赖spring-boot-starter-jdbc时,框架会自动为我们的项目注入事务管理器对象,最常用的为DataSourceTransactionManager对象。

Spring 中事务管理实现

本小节重点讲解实际项目中最常用的注解方式的事务管理,以注解@Transactional配置方式为例,进行实践分析。基于@Transactional 注解进行声明式事务管理的实现步骤分为两步:

  1. 启用声明式事务管理,在配置类上添加@EnableTransactionManagement,新版本中也可不添加(例如新版Spring Boot项目)。
  2. 将@Transactional注解添加到合适的业务类或方法上,并设置合适的属性信息。
@Transactional(isolation = Isolation.READ_COMMITTED,//隔离等级
               rollbackFor = Throwable.class,//回滚
               readOnly = false,//读的时候不加锁
               timeout = 30,//超过30秒抛出异常
               propagation = Propagation.REQUIRED) //传播
//共性
public class SysUserServiceImpl implements SysUserService {

	@Autowired
	private SysUserDao sysUserDao;
	
	@Autowired
	private SysUserRoleDao sysUserRoleDao;
	
	@Transactional(readOnly = true)//个性(只读)readOnly事务中不允许执行更新操作
	@RequiredLog(operation = "分页查询")
	//@Override
	public PageObject<SysUserDept> findPageObjects(String username,Integer pageCurrent){
		...
	}
}

其中,代码中的@Transactional注解用于描述类或方法,告诉spring框架我们要在此类的方法执行时进行事务控制,其具体说明如下:

  • 当@Transactional注解应用在类上时表示类中所有方法启动事务管理,并且一般用于事务共性的定义。
  • 当@Transactional描述方法时表示此方法要进行事务管理,假如类和方法上都有@Transactional注解,则方法上的注解一般用于事务特性的定义。
  • @Transactional 常用属性应用说明:
  • timeout:事务的超时时间,默认值为-1,表示没有超时显示。如果配置了具体时间,则超过该时间限制但事务还没有完成,则自动回滚事务。
  • read-only:指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
  • rollback-for:用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。
  • no-rollback- for 抛出 no-rollback-for 指定的异常类型,不回滚事务。
  • isolation事务的隔离级别,默认值采用 DEFAULT。
    Spring 中事务控制过程分析
    在这里插入图片描述
    Spring事务管理是基于接口代理(JDK)或动态字节码(CGLIB)技术,然后通过AOP实施事务增强的。当我们执行添加了事务特性的目标方式时,系统会通过目标对象的代理对象调用DataSourceTransactionManager对象,在事务开始的时,执行doBegin方法,事务结束时执行doCommit或doRollback方法。

Spring 中事务传播特性

事务传播(Propagation)特性指"不同业务(service)对象"中的事务方法之间相互调用时,事务的传播方式
在这里插入图片描述
其中,常用事务传播方式如下:

  • @Transactional(propagation=Propagation.REQUIRED) 。

如果没有事务创建新事务, 如果当前有事务参与当前事务, Spring 默认的事务传播行为是PROPAGATION_REQUIRED,它适合于绝大多数的情况。假设 ServiveX#methodX() 都工作在事务环境下(即都被 Spring 事务增强了),假设程序中存在如下的调用链:
Service1#method1()->Service2#method2()->Service3#method3(),那么这 3 个服务类的 3 个方法通过 Spring 的事务传播机制都工作在同一个事务中。
在这里插入图片描述

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public List<Node> findZtreeMenuNodes() {
		return sysMenuDao.findZtreeMenuNodes();
	}

当有一个业务对象调用如上方法时,此方法始终工作在一个已经存在的事务方法,或者是由调用者创建的一个事务方法中。

  • @Transactional(propagation=Propagation.REQUIRES_NEW)
    必须是新事务, 如果有当前事务, 挂起当前事务并且开启新事务

   @Transactional(propagation = Propagation.REQUIRES_NEW)
	@Override
	public void saveObject(SysLog entity) {
	  sysLogDao.insertObject(entity);
	}

当有一个业务对象调用如上业务方法时,此方法会始终运行在一个新的事务中。

Spring 中事务管理小结

Spring 声明式事务是 Spring 最核心,最常用的功能。由于 Spring 通过 IOC 和 AOP的功能非常透明地实现了声明式事务的功能,对于一般的开发者基本上无须了解 Spring声明式事务的内部细节,仅需要懂得如何配置就可以了。但对于中高端开发者还需要了解其内部机制。

猜你喜欢

转载自blog.csdn.net/SkyCloud_/article/details/108108208