浅谈spring中isolation和propagation的用法

我们来一步步详细讲解。

简介

在Spring中,@Transactional注解可以用于标注事务处理的方法,其中isolationpropagation两个属性用来设置事务的隔离级别和传播特性。本文将主要围绕这两个属性展开讲解。

隔离级别

事务隔离级别是解决数据库并发访问引发的一系列问题的标准。Spring框架提供了五种不同的隔离级别,分别是:

  • ISOLATION_DEFAULT:采用默认的数据库隔离级别。
  • ISOLATION_READ_UNCOMMITTED:读取未提交的数据,该隔离级别存在数据不一致的问题。
  • ISOLATION_READ_COMMITTED:读取已提交的数据,可以避免脏读问题。
  • ISOLATION_REPEATABLE_READ:可以多次读取同一件事物的数据,可以防止脏读和不可重复的读问题。
  • ISOLATION_SERIALIZABLE:最高的隔离级别,可以防止脏读、不可重复的读和幻读问题。

传播特性

在Spring框架中,一个事务方法内部还可以调用其他事务方法,这时就需要使用传播特性来控制事务的传播方式。Spring提供了7种传播特性,分别是:

  • PROPAGATION_REQUIRED:如果当前存在一个事务,则加入该事务,否则创建一个新事务。
  • PROPAGATION_SUPPORTS:如果当前存在一个事务,则加入该事务,否则按非事务方式执行。
  • PROPAGATION_MANDATORY:如果当前存在一个事务,则加入该事务,否则抛出异常。
  • PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则将当前事务挂起。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则将当前事务挂起。
  • PROPAGATION_NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。
  • PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务中执行。如果没有事务则按照REQUIRED执行。

示例

下面我们通过两个示例来演示这两个属性。

示例1:隔离级别的设置

/**
 * 隔离级别的示例类
 */
@Service
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
public class IsolationService {

    @Autowired
    private UserDao userDao;

    /**
     * 转账方法
     *
     * @param from   转出账户
     * @param to     转入账户
     * @param amount 转账金额
     */
    public void transfer(String from, String to, double amount) {

        // 查询转出账户并扣除余额
        User fromUser = userDao.getUserByName(from);
        fromUser.setAmount(fromUser.getAmount() - amount);
        userDao.updateUser(fromUser);

        // 查询转入账户并增加余额
        User toUser = userDao.getUserByName(to);
        toUser.setAmount(toUser.getAmount() + amount);
        userDao.updateUser(toUser);

    }
}

在上面的示例中,我们通过@Transactional注解设置了事务的隔离级别为ISOLATION_REPEATABLE_READ,传播特性为PROPAGATION_REQUIRES_NEW

该示例中的transfer方法用于实现两个用户之间的转账操作,其中查询用户并修改余额的过程,需要保证在同一个事务中执行,而且在查询不同用户的余额时也需要保证数据的一致性,因此需要将事务的隔离级别设置为ISOLATION_REPEATABLE_READ

而且在转账过程中,如果出现异常需要回滚时,需要只回滚当前事务,而不回滚之前的事务,因此需要将传播特性设置为PROPAGATION_REQUIRES_NEW

示例2:传播特性的设置

/**
 * 传播特性的示例类
 */
@Service
@Transactional
public class PropagationService {

    @Autowired
    private IsolationService isolationService;

    @Autowired
    private UserDao userDao;

    public void withdraw(String userName, double amount) {

        User user = userDao.getUserByName(userName);
        user.setAmount(user.getAmount() - amount);
        userDao.updateUser(user);

    }

    public void transfer(String from, String to, double amount) {

        isolationService.transfer(from, to, amount);

    }

    public void pay(String from, String to, double amount) {

        // 模拟支付过程
        withdraw(from, amount);

        // 模拟转账过程
        transfer(from, to, amount);

    }

}

在上面这个示例中,我们实现了一个支付流程,其中模拟了从一个用户账户中扣款和向另一个用户账户转账两个操作。这两个操作都是在事务内部进行的。而在最终的支付流程中,需要先完成扣款操作,然后再进行转账操作。也就是说,如果扣款操作失败,则转账操作不应该执行。

但是如果我们只在withdraw方法上加@Transactional注解,而不加在pay方法上,则在withdraw方法执行之后,即使发生异常,余额也已经被减少了,这是不可取的。因此,我们需要将pay方法也加上@Transactional注解,并设置其传播特性为PROPAGATION_REQUIRES_NEW,这样才能做到各自独立的事务,出现异常时互不干扰。

总结

在Spring框架中,@Transactional注解是非常常用的,特别是在服务层开发中。isolationpropagation两个属性可以用于控制事务的隔离级别和传播特性,帮助我们实现各种不同的事务场景。掌握这两个属性的使用方式,对于实现可靠的业务逻辑非常重要。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈spring中isolation和propagation的用法 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • JavaScript中set与get方法用法示例

    一、什么是set方法和get方法 在JavaScript中,set方法和get方法是一种访问对象属性的方式。通常情况下,使用普通的属性访问方式,可以读写对象的属性。但是如果希望对属性进行精细的控制,就需要使用set方法和get方法。 set方法和get方法的作用是:分别用于设置和获取属性的值。在调用set方法时,会将值保存在特殊的临时变量中,而在调用get方…

    JavaScript 2023年5月28日
    00
  • 浅谈关于JS下大批量异步任务按顺序执行解决方案一点思考

    关于JS下大批量异步任务按顺序执行的解决方案,一般来说有以下几种: 解决方案一:使用async/await async/await 是 ES2017 中引入的语法糖,可以用来消灭异步回调地狱,提高代码可读性。下面是一个示例: async function runInOrder(list) { for (const func of list) { await …

    JavaScript 2023年5月27日
    00
  • javascript表单验证 – Parsley.js使用和配置

    JavaScript表单验证是Web开发过程中一个非常重要的环节,可以用于确保用户在提交表单时输入的数据格式正确且符合预期,从而提高应用程序的稳定性和可用性。 Parsley.js是一个轻量级的JavaScript表单验证库,可以有效地帮助开发人员构建和配置表单验证规则。下面是一份Parsley.js的配置攻略: 步骤1:安装Parsley.js 首先,需要…

    JavaScript 2023年6月10日
    00
  • 详解JavaScript中的执行上下文及调用堆栈

    我们来详细讲解一下“详解JavaScript中的执行上下文及调用堆栈”的攻略。 什么是执行上下文 当 JavaScript 代码执行一段可执行代码时,会创建对应的执行上下文。执行上下文可以理解为是当前 JavaScript 代码的执行环境或者说是当前代码执行时的上下文环境,它包含了当前执行代码所需的所有变量、函数、参数等信息。如果把生活中的场景来理解,执行上…

    JavaScript 2023年6月11日
    00
  • js鼠标按键事件和键盘按键事件用法实例汇总

    下面是“js鼠标按键事件和键盘按键事件用法实例汇总”的完整攻略。 一、鼠标按键事件 鼠标按键事件是指用户通过鼠标在网页上进行的操作,常用的鼠标按键事件有mousedown、mouseup、click、dbclick、mousemove等。 1. mousedown事件 mousedown事件在鼠标按下的时候触发,常用于实现鼠标拖动等交互效果。示例代码如下: …

    JavaScript 2023年5月28日
    00
  • JavaScript进阶教程(第二课续)第2/2页

    JavaScript进阶教程(第二课续)第2/2页攻略 一、概述 本教程将对JavaScript进阶知识进行详细讲解,其中包括以下三个部分: 进阶语法特性介绍 函数式编程介绍与应用 异步编程与Promise 二、进阶语法特性介绍 1. Rest参数 Rest参数允许在定义函数时使用不限数量的参数,这些参数将被自动转换为数组,方便对参数进行遍历: functi…

    JavaScript 2023年5月18日
    00
  • 异步安全加载javascript文件的方法

    异步安全加载JavaScript文件是指在保证网页性能和用户体验的同时,确保JavaScript代码能够无误地执行。下面是异步安全加载JavaScript文件的方法: 1. 异步加载JavaScript文件 异步加载JavaScript文件可以使用HTML5中的script标签,并且设置async属性。这样浏览器会异步加载脚本,不会阻塞网页的渲染,同时脚本在…

    JavaScript 2023年5月27日
    00
  • JavaScript作用域与作用域链优化方式

    我来介绍一下JavaScript作用域和作用域链的优化方式。 什么是JavaScript作用域 JavaScript作用域指的是变量和函数可访问的范围。在JavaScript中,作用域分为全局作用域和局部作用域。 全局作用域:指在代码的任何地方都可以访问的变量和函数,一般在页面的顶部定义。 var globalVar = "我是全局变量"…

    JavaScript 2023年6月11日
    00
合作推广
合作推广
分享本页
返回顶部