浅谈spring中isolation和propagation的用法

yizhihongxing

我们来一步步详细讲解。

简介

在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遍历td tr等html元素

    要遍历HTML元素,需要使用JavaScript。以下是遍历<td>, <tr>及`<table>元素的完整攻略: 遍历<table>元素 首先需要获取<table>元素的引用。可以使用document.getElementById()或document.querySelector()方法。示例如下…

    JavaScript 2023年6月10日
    00
  • 使用JS判断页面是首次被加载还是刷新

    使用JS判断页面是首次被加载还是刷新,可以使用sessionStorage来进行判断,具体方法如下: 监听load事件,在事件处理函数中,判断sessionStorage是否存在对应的键值对。如果存在,说明页面是刷新后再次加载,反之则是首次加载。 示例代码: window.addEventListener(‘load’, function() { var i…

    JavaScript 2023年6月11日
    00
  • Javascript处理DOM元素事件实现代码

    当我们需要在网页中添加交互功能时,JavaScript 处理 DOM 元素事件是必须掌握的技能。在接下来的回答中,我将介绍完整的攻略,帮助你学会如何使用 JavaScript 处理 DOM 元素事件。 什么是事件? 在编写网页时,事件是指用户操作网页时所触发的动作。例如,当用户点击一个按钮,就会触发 click 事件;当用户将光标移动到一个元素上时,会触发 …

    JavaScript 2023年6月11日
    00
  • 当ES6遇上字符串和正则表达式

    当ES6遇上字符串和正则表达式,能够大大提高我们的编程效率,以下内容将详细讲解ES6与字符串、正则表达式的操作。 字符串 1. 模板字符串 ES6中,我们可以使用模板字符串来更方便的输出变量。 模板字符串用反引号(`)来表示,用${}来表示变量。 示例: const name = ‘小明’; const age = 18; console.log(`我叫${…

    JavaScript 2023年6月11日
    00
  • 保证JavaScript和Asp、Php等后端程序间传值编码统一

    确保JavaScript和ASP、PHP等后端程序间传值编码统一是一个非常重要的问题,因为不同的编码方式会导致传递的值变得混乱和不可预测。下面是一些标准的攻略,可以确保这些问题被避免: 1. 统一字符编码 我们建议使用UTF-8字符编码,因为它是一种通用的编码方式,能够支持所有的字符,包括中文、日文和阿拉伯文等等。此外,UTF-8也是互联网上最常用的编码方式…

    JavaScript 2023年5月20日
    00
  • javascript之AJAX框架使用说明

    JavaScript之AJAX框架使用说明 什么是AJAX? AJAX(Asynchronous JavaScript and XML)指的是一种创建交互式 Web 应用程序的技术。使用 AJAX,JavaScript 和 XMLHttpRequest 对象一起实现无刷新数据更新。 使用 AJAX 可以在不重新加载整个页面的情况下,与服务器交换数据并更新部分…

    JavaScript 2023年6月11日
    00
  • JScript内置对象Array中元素的删除方法

    针对JScript内置对象Array中元素的删除方法,可以采取以下两种方式: 方法一:使用splice方法 Array对象的splice()方法可以用来删除元素,并向数组添加新元素。 其语法如下: array.splice(start, deleteCount, item1, item2, …) 参数说明: start:必需,整数,规定数组中开始删除和添…

    JavaScript 2023年6月11日
    00
  • node puppeteer(headless chrome)实现网站登录

    下面我将介绍如何使用Node.js中的Puppeteer库实现网站登录的完整攻略。在此过程中,我将提供两个示例以帮助您更好地理解。 简介 Puppeteer是由Google开发的一个Node.js库,它提供了一组API来使用Headless Chrome浏览器进行自动化测试、爬虫或屏幕截图等操作。Headless Chrome是Chrome浏览器的无界面版本…

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