当前位置: 首页 > article >正文

Spring事务类型及传播行为实战指南

Spring事务类型及传播行为实战指南

在Spring框架中,事务管理是确保数据一致性和完整性的关键部分。通过合理的事务管理,可以确保在数据库操作过程中的原子性、一致性、隔离性和持久性。本文将从Spring事务的基础概念、事务类型、传播行为以及实战案例等方面进行详细讲解。

一、Spring事务基础

1.1 事务概述

事务是一组数据库操作的逻辑单元,具有原子性、一致性、隔离性和持久性(ACID)四个特性。在Spring中,事务管理提供了一种可靠且灵活的方式来管理这些操作,确保数据的一致性和完整性。

  • 原子性(Atomicity):事务中的所有操作要么全部成功执行并提交,要么全部失败并回滚,保持数据的一致性。
  • 一致性(Consistency):事务的执行过程中,数据库从一个一致的状态转变为另一个一致的状态,不会破坏数据的完整性。
  • 隔离性(Isolation):多个并发事务之间应该相互隔离,每个事务的操作应该看起来像是在独立执行,避免数据冲突和不一致性。
  • 持久性(Durability):一旦事务提交,其对数据库的修改应该是永久性的,即使在系统故障或重启后也能够恢复。

1.2 事务管理器

事务管理器是Spring提供的一个接口,用于管理事务的开始、提交和回滚操作。它与底层的数据库或持久化框架进行交互,并确保事务的正确执行。Spring提供了多种事务管理器,如DataSourceTransactionManagerJpaTransactionManagerHibernateTransactionManagerJtaTransactionManager等,以适应不同的应用场景和开发需求。

1.3 事务定义和注解

事务定义(Transaction Definition)定义了事务的属性,如隔离级别、传播行为、超时设置等。在Spring中,事务定义可以通过编程方式或声明式方式来定义。声明式事务定义是通过在方法或类级别上使用注解或XML配置来定义事务的属性。Spring提供了@Transactional注解,用于在方法级别上定义事务的属性。

二、事务类型

Spring支持两种主要的事务管理方式:编程式事务管理和声明式事务管理。

2.1 编程式事务管理

编程式事务管理通过编写代码来显式地管理事务的开始、提交和回滚。这种方式提供了更高的灵活性,但代码量较大,容易出错。Spring提供了TransactionTemplate等工具类来简化编程式事务管理的实现。

2.2 声明式事务管理

声明式事务管理通过注解或XML配置来定义事务的边界和属性,无需在代码中显式地编写事务管理代码。这种方式使事务管理与业务逻辑分离,简化了代码,提高了可维护性。@Transactional注解是声明式事务管理中最常用的方式。

三、事务传播行为

事务传播行为(propagation behavior)指的是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何运行。Spring在TransactionDefinition接口中规定了7种类型的事务传播行为。

3.1 REQUIRED

  • 行为描述:如果当前存在事务,则加入该事务中执行;如果当前没有事务,则创建一个新的事务执行。这是Spring默认的传播行为。
  • 应用场景:适用于大多数需要事务支持的方法,特别是当方法可能被其他事务方法调用时。

3.2 REQUIRES_NEW

  • 行为描述:总是创建一个新的事务,并挂起当前事务(如果存在)。在新的事务中执行方法,不受外部事务的影响。
  • 应用场景:适用于需要确保方法执行完全独立于外部事务的场景,例如,在嵌套事务中需要完全隔离的操作。

3.3 SUPPORTS

  • 行为描述:如果当前存在事务,就加入该事务;如果当前不存在事务,就以非事务方式执行。
  • 应用场景:适用于那些对事务没有强制要求的方法,但在有事务存在时可以参与。

3.4 NOT_SUPPORTED

  • 行为描述:如果当前存在事务,就把当前事务挂起。以非事务方式执行方法。
  • 应用场景:适用于那些不需要事务支持的操作,例如,读取数据但不修改数据的操作。

3.5 MANDATORY

  • 行为描述:如果当前存在事务,就加入该事务;如果当前不存在事务,就抛出异常。
  • 应用场景:适用于那些必须在事务中执行的方法,确保操作的原子性和一致性。

3.6 NEVER

  • 行为描述:以非事务方式执行方法,如果当前存在事务,则抛出异常。
  • 应用场景:适用于那些绝对不能在事务中执行的操作,确保操作的独立性。

3.7 NESTED

  • 行为描述:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就创建一个新事务。
  • 应用场景:适用于需要在当前事务内部执行一个具有部分回滚能力的子事务的场景。

四、实战案例

4.1 场景描述

假设有一个电商系统,其中包括用户购买商品的操作。购买操作涉及到多个数据库操作,如库存减少、用户余额减少等,这些操作需要在一个事务中完成,以确保数据的一致性。

4.2 实现步骤

  1. 定义服务层接口和实现

    定义一个BookShopService接口和它的实现类BookShopServiceImpl,用于处理购买商品的业务逻辑。

    public interface BookShopService {
        void purchase(String username, String isbn);
    }
    
    @Service
    @Transactional(propagation = Propagation.REQUIRED)
    public class BookShopServiceImpl implements BookShopService {
        @Autowired
        private BookShopDao bookShopDao;
    
        @Override
        public void purchase(String username, String isbn) {
            // 1. 获取书的单价
            int price = bookShopDao.findBookPriceByIsbn(isbn);
            // 2. 更新书的库存
            bookShopDao.updateBookStock(isbn);
            // 3. 更新用户的余额
            bookShopDao.updateUserAccount(username, price);
        }
    }
    

    注意,在BookShopServiceImpl类上使用了@Transactional注解,并指定了传播行为为REQUIRED。这意味着如果当前存在事务,则购买操作将加入该事务;如果当前没有事务,则创建一个新的事务。

  2. 调用服务层方法

    在需要购买商品的地方,直接调用BookShopServicepurchase方法即可。

    @Autowired
    private BookShopService bookShopService;
    
    public void checkout(String username, List<String> isbns) {
        for (String isbn : isbns) {
            bookShopService.purchase(username, isbn);
        }
    }
    

    由于purchase方法已经通过@Transactional注解声明了事务,因此在checkout方法中调用purchase方法时,所有的购买操作将在一个事务中完成,确保数据的一致性。

4.3 隔离级别和错误处理

在实际应用中,还需要根据业务需求设置合适的隔离级别,并在发生错误时进行适当的错误处理和事务回滚。

  • 设置隔离级别:可以通过@Transactional注解的isolation属性来设置隔离级别。
  • 错误处理:在purchase方法中,如果发生异常,Spring将自动回滚事务,确保数据的一致性。

五、总结

Spring事务管理提供了可靠且灵活的方式来管理数据库操作中的事务,确保数据的一致性和完整性。通过合理使用事务类型和传播行为,可以灵活地控制事务的边界和行为,满足各种业务需求。在实际开发中,应根据具体业务场景选择合适的事务管理方式,并合理设置事务属性和隔离级别,以确保系统的稳定性和可靠性。


http://www.kler.cn/news/317506.html

相关文章:

  • JEDEC DDR4 SRAM standard
  • go 读取excel数据存储到mysql
  • 案例研究丨国控星鲨利用DataEase释放数据潜能,重塑业务视野
  • 从底层原理上解释 ClickHouse 的索引
  • leetcode 205.同构字符串
  • 如何快速上手一个Github的开源项目
  • C++ 9.24
  • 如何使用ssm实现疫苗预约系统+vue
  • 使用synchronized锁住字符串
  • Shire 智能体市场:IDE 一键安装多智能体,协同打造集体智慧 Copilot
  • 迎国庆-为祖国庆生python、Java、C各显神通
  • 【Python】数据可视化之分布图
  • 联影医疗嵌入式面试题及参考答案(3万字长文)
  • wpf,工具栏上,最小化按钮的实现
  • ubuntu 系统下,安装stable diffusion解决下载速度慢的问题
  • (十五)、把自己的镜像推送到 DockerHub
  • 数模方法论-无约束问题求解
  • 科龙睡眠空调小耳朵LF上线,“亲身”答疑空调一天多少度电
  • 【二十五】【QT开发应用】无边窗窗口鼠标拖动窗口移动,重写mousePressEvent,mouseMoveEvent函数
  • 专属文生图助手——SD3+ComfyUI文生图部署步骤
  • 安卓Settings值原理源码剖析存储最大的字符数量是多少?
  • css设置动态数组渲染及中间线平均分开显示
  • IMX6UL开发板中断实验(三)
  • 深度学习02-pytorch-01-张量的创建
  • 使用python-pptx拆分PPT文档:将一个PPT文件拆分成多个小的PPT文件
  • 某yandex图标点选验证码逆向
  • 使用双向 LSTM 和 CRF 进行中文命名实体识别
  • Spring全家桶
  • 图为科技大模型一体机,智领未来社区服务
  • C++中stack类和queue类