写点什么

6 个 Spring tx 事务注解:4 种隔离 &7 种事务传播业务案例 (必须收藏)

作者:肖哥弹架构
  • 2024-08-20
    河北
  • 本文字数:4739 字

    阅读完需:约 16 分钟

6 个Spring tx 事务注解:4种隔离&7种事务传播业务案例(必须收藏)

Spring 框架的事务管理模块,通过一系列注解提供了一种强大而灵活的方式来处理企业级 Java 应用程序中的事务。@Transactional注解是这一模块的核心,它支持多种事务属性,如传播行为、隔离级别和超时设置,允许开发者以声明式的方式管理事务的边界和特性。此外,@Propagation@Isolation@EnableTransactionManagement等注解进一步丰富了 Spring 的事务管理能力,使得开发者可以根据不同的业务场景定制事务策略。这些注解的使用不仅简化了事务代码的编写,还提高了应用程序的健壮性和可测试性。Spring 事务管理的声明式特性,让开发者能够将业务逻辑与事务管理逻辑分离,从而创建出更加清晰、可维护的代码结构。


肖哥弹架构 跟大家“弹弹” 框架注解使用,需要代码关注

欢迎 点赞,关注,评论。

关注公号 Solomon 肖哥弹架构获取更多精彩内容

历史热点文章

6 个注解说明

@Transactional

1.1 注解作用介绍


@Transactional 注解用于声明方法或类,确保它们在事务的上下文中执行。这是 Spring 中处理事务的最常用方式。1.2 注解属性介绍


  • value: 指定事务管理器的名称。

  • timeout: 以秒为单位设置事务的超时时间。

  • readOnly: 指示事务是否为只读事务。

  • rollbackFor: 指定导致事务回滚的异常类数组。

  • noRollbackFor: 指定即使抛出这些异常也不触发事务回滚的类数组。

  • propagation: 指定事务的传播行为,默认为Propagation.REQUIRED

  • isolation: 指定事务的隔离级别,默认使用底层数据库的默认隔离级别。


1.3 注解业务案例


@Transactional(    value = "customTransactionManager",     timeout = 5,     readOnly = false,     rollbackFor = {IllegalArgumentException.class, CustomException.class},     noRollbackFor = {NoRollbackException.class},     propagation = Propagation.REQUIRED,    isolation = Isolation.READ_COMMITTED)public void updateUserBalance(Long userId, int amount) {    // 业务逻辑,如更新用户余额    accountRepository.updateBalance(userId, amount);    if (accountRepository.getBalance(userId) < 0) {        throw new CustomException("Insufficient funds");    }}
复制代码

@EnableTransactionManagement

2.1 注解作用介绍


@EnableTransactionManagement 注解用于开启基于注解的事务管理,允许在 Spring 应用程序中使用@Transactional注解。


2.2 注解属性介绍


  • 无特定属性。


2.3 注解业务案例


@Configuration@EnableTransactionManagementpublic class TransactionManagementConfig {    // 其他配置}
复制代码

@TransactionManagementConfigurer

3.1 注解作用介绍


@TransactionManagementConfigurer 注解用于自定义事务管理器的配置,适用于需要自定义事务管理器时。


3.2 注解属性介绍


  • 无特定属性。


3.3 注解业务案例


@Configurationpublic class CustomTransactionManagementConfig implements TransactionManagementConfigurer {    @Override    public PlatformTransactionManager annotationDrivenTransactionManager() {        return new MyCustomTransactionManager();    }}
复制代码

@Propagation

4.1 注解作用介绍


@Propagation 注解用于指定事务的传播行为,与@Transactional注解的propagation属性配合使用。


4.2 注解属性介绍


  • value: 指定事务的传播行为,如Propagation.REQUIREDPropagation.REQUIRES_NEW等。


4.3 注解业务案例


java@Transactional(propagation = Propagation.REQUIRES_NEW)public void someTransactionalMethod() {    // 业务逻辑}
复制代码

@Isolation

5.1 注解作用介绍 @Isolation 注解用于设置事务的隔离级别,与@Transactional注解的isolation属性配合使用。


5.2 注解属性介绍


  • value: 指定隔离级别,如Isolation.READ_COMMITTEDIsolation.REPEATABLE_READ等。


5.3 注解业务案例


java@Transactional(isolation = Isolation.REPEATABLE_READ)public void someTransactionalMethod() {    // 业务逻辑}
复制代码

@TransactionAttribute

6.1 注解作用介绍


@TransactionAttribute 注解用于指定事务的具体属性,如传播行为和隔离级别,通常与@Transactional注解配合使用。


6.2 注解属性介绍


  • value: 指定事务属性的组合。


6.3 注解业务案例


@Transactional(    transactionAttribute = @TransactionAttribute(        readOnly = true,         propagation = Propagation.SUPPORTS    ))public void someTransactionalMethod() {    // 业务逻辑}
复制代码


@Propagation@Isolation@TransactionAttribute注解通常作为@Transactional注解的参数使用,而不是单独使用。@EnableTransactionManagement@TransactionManagementConfigurer注解用于配置 Spring 的事务管理能力。

4 种隔离策略案例说明

Isolation.DEFAULT

@Transactional(isolation = Isolation.DEFAULT)public void processUserOrder() {    // 业务逻辑,使用数据库默认隔离级别}
复制代码


  • 使用条件: 使用数据库默认隔离级别,适用于大多数标准业务逻辑,不特别指定隔离级别以利用数据库的默认配置,适合于那些对隔离级别没有特别要求的场景。

  • 业务案例举例: 在处理用户订单时,如果业务逻辑不涉及复杂的并发操作,使用默认隔离级别可以确保与数据库配置的一致性,同时简化事务管理。

Isolation.READ_UNCOMMITTED

@Transactional(isolation = Isolation.READ_UNCOMMITTED)public void generateInventoryReport() {    // 生成库存报告,允许读取未提交的数据}
复制代码


  • 使用条件: 在生成报告或统计数据时,可能不需要完全的数据一致性,此时可以牺牲一点一致性以换取更高的并发性能,适合于那些对数据实时性要求不高的报告生成场景。

  • 业务案例举例: 当生成月末库存报告时,由于报告的目的是提供概览信息,而不是用于交易处理,因此可以接受读取到未提交的事务数据。

Isolation.READ_COMMITTED

@Transactional(isolation = Isolation.READ_COMMITTED)public void transferFunds(AccountId from, AccountId to, BigDecimal amount) {    // 资金从一个账户转移到另一个账户}
复制代码


  • 使用条件: 保证在事务中读取的数据是其他事务已经提交的数据,适用于需要避免读取到其他未提交事务影响的数据的金融交易场景。

  • 业务案例举例: 在执行银行账户之间的资金转账时,必须确保转账操作基于已提交的账户余额,以防止出现不一致的财务记录。

Isolation.REPEATABLE_READ

@Transactional(isolation = Isolation.REPEATABLE_READ)public void checkAndConfirmBooking(BookingId bookingId) {    // 检查预订信息并确认预订}
复制代码


  • 使用条件: 在处理过程中需要多次读取同一数据集,保证这些数据在事务过程中的一致性,适用于库存检查和订单处理,确保库存数据不被其他事务修改。

  • 业务案例举例: 在旅游预订系统中确认客户预订时,需要多次检查房间的可用性,以确保在确认过程中房间不会被其他客户预订。

Isolation.SERIALIZABLE

@Transactional(isolation = Isolation.SERIALIZABLE)public void updateCriticalSystemParameters() {    // 更新关键系统参数}
复制代码


  • 使用条件: 对于更新关键配置或敏感数据,需要确保完全的隔离,避免并发访问导致的数据不一致,虽然这会牺牲一定的并发性能。

  • 业务案例举例: 当需要更新影响系统全局运行的关键参数(如交易费用率)时,使用最高隔离级别可以确保更新操作的原子性和一致性,防止配置错误。

事务 7 种传播机制说明

Propagation.REQUIRED

  • 案例:


    java    public class OrderService {        @Transactional(Propagation.REQUIRED)        public void processOrder(Order order) {            // 保存订单            saveOrder(order);            // 扣减库存            reduceInventory(order);        }    }
复制代码


  • 使用条件Propagation.REQUIRED是默认设置,适用于大多数业务逻辑,确保方法在事务上下文中执行,如果当前存在事务,则加入该事务;如果不存在,则新建一个。

  • 方法场景: 当需要执行一系列数据库操作,这些操作需要作为一个单一的原子工作单元被提交或回滚,例如处理订单时既要保存订单信息又要扣减库存。

Propagation.REQUIRES_NEW

public class UserService {    @Transactional(Propagation.REQUIRES_NEW)    public void deleteUser(User user) {        // 删除用户        userRepository.delete(user);        // 清除用户相关数据        clearUserData(user);    }}
复制代码


  • 使用条件: 当需要执行一个新事务,并且这个新事务必须独立于任何现有事务时使用,即使存在一个活动的事务,REQUIRES_NEW也会创建一个新的事务。

  • 方法场景: 在删除用户时,可能需要确保删除操作在一个新的事务中执行,以避免由于现有事务的回滚而影响到删除操作。

Propagation.SUPPORTS

public class ProductService {    @Transactional(Propagation.SUPPORTS)    public List<Product> listProducts() {        // 返回产品列表        return productService.findAll();    }}
复制代码


  • 使用条件: 当事务方法被调用时,如果已经存在一个事务,它应该在该事务的上下文中执行;如果没有事务存在,它应该非事务性地执行。

  • 方法场景: 查询操作,如列出所有产品的列表,如果存在事务,则在事务中执行查询,否则进行普通的查询。

Propagation.MANDATORY

public class AccountService {    @Transactional(Propagation.MANDATORY)    public void transferFunds(Account from, Account to, BigDecimal amount) {        // 从from账户扣款        from.debit(amount);        // 给to账户加款        to.credit(amount);    }}
复制代码


  • 使用条件: 事务方法是在一个必须存在事务的上下文中被调用,如果不存在事务,抛出异常。

  • 方法场景: 执行资金转账时,必须确保在事务的上下文中执行,以保证资金的准确性和一致性。

Propagation.NESTED

public class TransactionService {    @Transactional    public void executeTransactions() {        // 开启一个事务        performTransaction();        // 嵌套事务,进行更细粒度的操作        @Transactional(Propagation.NESTED)        performNestedTransaction();    }}
复制代码


  • 使用条件: 需要在现有的事务中执行一个或多个操作,这些操作需要自己的事务上下文,例如,保存点或额外的隔离级别。

  • 方法场景: 在执行一系列需要额外事务控制的事务时,如在主事务中执行额外的事务以处理更细粒度的业务逻辑。

Propagation.NOT_SUPPORTED

public class CacheService {    @Transactional(Propagation.NOT_SUPPORTED)    public void refreshCache() {        // 刷新缓存,不需要事务        cacheManager.clearCache();    }}
复制代码


  • 使用条件: 事务方法不应该运行在任何事务上下文中,如果存在一个活动的事务,它应该被挂起。

  • 方法场景: 执行不需要事务的操作,如刷新缓存,以避免与可能存在的事务冲突。

Propagation.NEVER

public class AuditService {    @Transactional(Propagation.NEVER)    public void logAuditEvent(AuditEvent event) {        // 记录审计事件,不允许在事务上下文中执行        auditRepository.save(event);    }}
复制代码


  • 使用条件: 事务方法不应该运行在任何事务上下文中,如果存在一个活动的事务,抛出异常。

  • 方法场景: 记录审计事件时,需要确保这些记录操作不会受到任何现有事务的影响,以保证审计数据的完整性。

用户头像

智慧属心窍之锁 2019-05-27 加入

擅长于通信协议、微服务架构、框架设计、消息队列、服务治理、PAAS、SAAS、ACE\ACP、大模型

评论

发布
暂无评论
6 个Spring tx 事务注解:4种隔离&7种事务传播业务案例(必须收藏)_Java_肖哥弹架构_InfoQ写作社区