天天看点

Spring完整揭秘(九):Spring的事务管理

文章目录

  • ​​认识事务​​
  • ​​Spring事务架构​​
  • ​​TransactionDefinition 接口:​​
  • ​​TransactionStatus 接口​​
  • ​​PlatformTransactionManager接口​​
  • ​​Spring 声明式事务管理​​
  • ​​基于 @Transactional 的声明式事务管理​​
  • ​​@Transactional声明式事务的例子​​

认识事务

  • 以可控的方式对数据资源进行访问的一组操作称为事务;在事务执行前后,数据资源所承载的系统状态始终处于正确的状态。
  • 事务特性(ACID)
  1. 原子性(Atomicity):事务包括的全部操作是一个整体,象原子一样不可分割。这些操作要么全部提交成功,但只要其中一个操作失败,则全部失败。
  2. 一致性(Consistency):保证事务开始和结束之间的中间状态不会被其他事务看到。
  3. 隔离性(Isolation):适当的破坏一致性来提升性能与并行度 。
  4. 持久性(Durability):每一次的事务提交后就会保证不会丢失。
  • 事务隔离性的从弱到强分别为
  1. Read Uncommitted(读取未提交内容)
  2. Read Committed(读取提交内容)
  3. Repeatable Read(可重读)
  4. Serializable(可串行化)
  • 事务职离级别越 强,一致性越好,并发性越差。

Spring事务架构

  • Spring的事务抽象包括3个主要接口:
  1. PlatformTransactionManager事务管理器。
  2. TransactionDefinition事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)。
  3. TransactionStatus事务运行状态。
Spring完整揭秘(九):Spring的事务管理
TransactionDefinition 接口:
  • 当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。Spring定义了七种传播行为:
定义 说明
PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务,则加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 表示该方法必须在事务中运行,如果当前事务不存在,则会抛出一个异常。
PROPAGATION_REQUIRED_NEW 表示当前方法必须运行在它自己的事务中。一个新的事务将被启动。如果存在当前事务,在该方法执行期间,当前事务会被挂起。
PROPAGATION_NOT_SUPPORTED 表示该方法不应该运行在事务中。如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则会抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
TransactionStatus 接口
  • 在事务处理过程中,我们可以使用TransactionStatus 接口进行如下工作:
  1. 查询事务状态;
  2. 通过setRollbackOnly方法标记当前事务以使其回滚;
  3. 创建内部嵌套事务。
PlatformTransactionManager接口
  • Spring的事务抽象框架以PlatformTransactionManager作为顶层抽象接口,具体的实现交给不同的实现类,使用对象可以根据当前场景,选择使用或者替换哪一个具体的实现类。
  • Spring完整揭秘(九):Spring的事务管理

Spring 声明式事务管理

  • 随着SpringBoot的诞生与推广,基于注解的声明式事务管理已经得到了广泛使用。声明式事务管理是建立在 Spring AOP
基于 @Transactional 的声明式事务管理
  1. 配置文件开启注解驱动,在相关的类和方法上通过注解@Transactional标识。
  2. Spring 在启动的时候会去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transaction的相关参数进行相关配置注入。
  3. 真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。
Spring完整揭秘(九):Spring的事务管理
  • @Transactional 注解的属性信息
属性名 说明
name 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器。
propagation 事务的传播行为,默认值为 REQUIRED。
isolation 事务的隔离度,默认值采用 DEFAULT。
timeout 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
read-only 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
@Transactional声明式事务的例子
/**
* 基于 @Transactional 的声明式事务管理
*/
@Service
public class UserService {

    // Spring Data JPA
    @Autowired
    private UserRepository userRepository;
    // Mybatis
    @Autowired
    private UserMapper userMapper;
    // DAO
    @Autowired
    private UserDAOImpl userDAO;

    // 返回所有的用户
    @Transactional(readOnly = true,timeout = 20)
    public List<User> listUsers() {
        return (List<User>) userRepository.findAll();
    }

    // 保存用户
    @Transactional(rollbackFor = Exception.class)
    public User saveUser(User user) {
        userDAO.addUser(user);
        if (user.getName().contains("admin")) {
            throw new RuntimeException("名称中不能含有admin");
        }
        return user;
    }

    // 删除用户
    @Transactional
    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }

    // 查找用户
    @Transactional(readOnly = true)
    public User findUser(Long id) {
        return userRepository.findById(id).get();
    }

    // 根据名称查找用户--Mybatis
    @Transactional(readOnly = true)
    public List<User> searchUser(String name) {
        return userMapper.findByName(name);
    }
}