浅谈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日

相关文章

  • 基于JS快速实现导航下拉菜单动画效果附源码下载

    关于“基于JS快速实现导航下拉菜单动画效果附源码下载”的完整攻略,我将从以下几个方面说明: 实现原理 开发步骤 源码下载 实现原理 在实现导航下拉菜单动画效果的过程中,我们可以使用JavaScript来控制菜单的显示和隐藏。具体过程如下: 鼠标移动到菜单的触发元素上时,显示下拉菜单。这里可以使用CSS的:hover伪类来实现鼠标移入和移出的效果。 显示下拉菜…

    JavaScript 2023年6月11日
    00
  • JavaScript中的迭代器和生成器详解

    JavaScript中的迭代器和生成器详解 什么是迭代器? 在 JavaScript 中,迭代器是一种设计模式,用于处理不同类型的数据集合并允许你遍历这些数据集合。迭代器可以存储在变量中,并且可以使用next()方法获取下一个元素,一般会返回一个对象包含两个属性,value和done,分别表示迭代器的当前值和是否已经迭代完成。 迭代器可以使用for…of…

    JavaScript 2023年5月28日
    00
  • HTML5 本地存储之如果没有数据库究竟会怎样

    这里是 “HTML5 本地存储之如果没有数据库究竟会怎样” 的攻略。 什么是本地存储 本地存储是Web开发中比较重要的一个概念,它可以在不使用服务器数据库的情况下,让我们的Web应用程序缓存数据。HTML5 中的本地存储提供了两种方式:localStorage 和 sessionStorage。 localStorage 存储的数据是永久性的,而 sessi…

    JavaScript 2023年6月11日
    00
  • JavaScript 对象创建的3种方法

    JavaScript对象创建一共有3种方式,它们分别是对象字面量、构造函数和Object.create()方法。 对象字面量 对象字面量是用花括号{}创建一个新对象的方式,使用最为广泛,也是最简单的一种。 示例一: // 创建一个对象字面量 const person = { name: "张三", age: 20, gender: &qu…

    JavaScript 2023年5月27日
    00
  • 深入理解JSON数据源格式

    深入理解JSON数据源格式 什么是JSON? JSON是JavaScript Object Notation的缩写,它是一种轻量级的数据交换格式,易于理解和使用。它基于一种JavaScript子集,但考虑到其实际用途,它是一种独立于语言的数据格式。JSON格式是一种键值对的数据结构,它采用Unicode字符集。 JSON的基本语法 JSON数据格式由两个大括…

    JavaScript 2023年5月27日
    00
  • 解决微信二次分享不显示摘要和图片的问题

    让微信二次分享能够正确显示摘要和图片,需要在网页head部分添加相关的meta标签。以下是具体的步骤: 在head部分添加以下meta标签: <meta property="og:title" content="网页标题"/> <meta property="og:description&q…

    JavaScript 2023年6月11日
    00
  • js实现倒计时及时间对象

    下面是详细讲解“JS实现倒计时及时间对象”的完整攻略。 时间对象 在 JavaScript 中,可以使用内置的时间对象 Date 来处理日期和时间。所以,我们可以借助 Date 对象来实现倒计时。 获取当前时间 首先,我们需要获取当前的时间。使用 new Date() 可以获取当前的日期和时间。 let now = new Date(); // 获取当前时间…

    JavaScript 2023年5月27日
    00
  • js 递归和定时器的实例解析

    JS 递归和定时器的实例解析 什么是递归? 递归是一种算法或函数设计技术,它是通过函数体内调用函数本身来完成的。通常情况下,递归函数是以递归式的表达式来定义的。简单来说,递归可以看作是把大的问题不断化解成相同的小问题,最终解决相同的小问题就能解决大的问题。 递归的示例 function sum(n) { if (n <= 1) return 1; re…

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