大疆Java面试被问:Spring事务的传播行为详解

一、事务传播行为概览

1. 7种传播行为总览

java

复制

下载

复制代码
// Propagation枚举定义
public enum Propagation {
    REQUIRED(0),      // 支持当前事务,不存在则新建(默认)
    SUPPORTS(1),      // 支持当前事务,不存在则以非事务运行
    MANDATORY(2),     // 支持当前事务,不存在则抛出异常
    REQUIRES_NEW(3),  // 新建事务,当前事务挂起
    NOT_SUPPORTED(4), // 非事务执行,当前事务挂起
    NEVER(5),         // 非事务执行,存在事务则抛出异常
    NESTED(6);        // 嵌套事务,不存在则新建
    
    private final int value;
}

2. 传播行为决策矩阵

text

复制

下载

复制代码
┌─────────────────────────────────────────────────────┐
│  当前是否存在事务? │    传播行为     │      结果        │
├───────────────────┼───────────────┼─────────────────┤
│       无          │   REQUIRED     │   创建新事务     │
│       有          │   REQUIRED     │   加入当前事务   │
│       无          │ SUPPORTS       │   无事务运行     │
│       有          │ SUPPORTS       │   加入当前事务   │
│       无          │   MANDATORY    │   抛出异常       │
│       有          │   MANDATORY    │   加入当前事务   │
│       无          │ REQUIRES_NEW   │   创建新事务     │
│       有          │ REQUIRES_NEW   │   挂起并新建     │
│       无          │ NOT_SUPPORTED  │   无事务运行     │
│       有          │ NOT_SUPPORTED  │   挂起并无事务   │
│       无          │     NEVER      │   无事务运行     │
│       有          │     NEVER      │   抛出异常       │
│       无          │    NESTED      │   创建新事务     │
│       有          │    NESTED      │   嵌套事务       │
└───────────────────┴───────────────┴─────────────────┘

二、每种传播行为深度解析

1. REQUIRED(默认传播行为)

场景分析

java

复制

下载

复制代码
@Service
public class OrderService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void createOrder(Order order) {
        // 业务逻辑1
        orderRepository.save(order);
        
        // 调用其他事务方法
        inventoryService.deductStock(order);  // REQUIRED
        couponService.useCoupon(order);       // REQUIRED
        
        // 异常模拟
        if (order.getAmount() > 10000) {
            throw new RuntimeException("金额过大");
        }
    }
}

@Service  
public class InventoryService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void deductStock(Order order) {
        // 减库存逻辑
        inventoryRepository.updateStock(order);
    }
}

// 执行流程:
// 1. OrderService.createOrder()开启事务T1
// 2. InventoryService.deductStock()加入T1事务
// 3. 如果InventoryService抛出异常,整个T1回滚
// 4. OrderService.createOrder()抛出异常,T1回滚
关键特性

java

复制

下载

复制代码
// 1. 事务共享
// 所有REQUIRED方法共享同一个物理连接
Connection conn = DataSourceUtils.getConnection(dataSource);

// 2. 异常传播
// 内层方法异常会传播到外层,导致整个事务回滚
try {
    methodA();  // REQUIRED
} catch (Exception e) {
    // methodA异常会导致外层事务回滚
    transactionManager.rollback(status);
}

// 3. 使用建议
// 适用于业务逻辑紧密关联的场景
// 如:订单创建 → 减库存 → 用优惠券

2. REQUIRES_NEW(新建独立事务)

场景分析

java

复制

下载

复制代码
@Service
public class OrderService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void processOrder(Order order) {
        // 主事务逻辑
        orderRepository.save(order);  // T1事务
        
        try {
            // 记录操作日志(独立事务)
            logService.addOperationLog(order);  // REQUIRES_NEW
        } catch (Exception e) {
            // 日志失败不影响主事务
            logger.error("记录日志失败", e);
        }
        
        // 发送消息(独立事务)
        messageService.sendOrderMessage(order);  // REQUIRES_NEW
    }
}

@Service
public class LogService {
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addOperationLog(Order order) {
        // 始终在新事务中执行
        operationLogRepository.save(buildLog(order));
        
        // 即使抛出异常,也不会影响外层事务
        if (System.currentTimeMillis() % 100 == 0) {
            throw new RuntimeException("随机日志失败");
        }
    }
}

// 执行流程:
// 1. OrderService.processOrder()开启事务T1
// 2. LogService.addOperationLog()挂起T1,开启新事务T2
// 3. T2提交或回滚后,恢复T1
// 4. T2的回滚不会影响T1
关键特性

java

复制

下载

复制代码
// 1. 事务隔离
// 每个REQUIRES_NEW方法有独立的事务和连接
// 物理上:每个事务使用不同的数据库连接

// 2. 事务挂起与恢复
TransactionStatus suspended = transactionManager.suspend(existing);
try {
    // 新事务逻辑
    TransactionStatus newStatus = transactionManager.begin(newDefinition);
    transactionManager.commit(newStatus);
} finally {
    transactionManager.resume(suspended);
}

// 3. 使用场景
// 日志记录、消息发送、异步任务提交
// 需要独立提交,失败不影响主业务的场景

3. NESTED(嵌套事务)

场景分析

java

复制

下载

复制代码
@Service
public class OrderService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void batchCreateOrders(List<Order> orders) {
        for (Order order : orders) {
            try {
                // 嵌套事务处理单个订单
                createSingleOrder(order);  // NESTED
            } catch (Exception e) {
                // 单个订单失败不影响其他订单
                logger.error("订单创建失败: {}", order.getId(), e);
            }
        }
    }
    
    @Transactional(propagation = Propagation.NESTED)
    public void createSingleOrder(Order order) {
        orderRepository.save(order);
        inventoryService.deductStock(order);  // REQUIRED
        
        // 模拟业务异常
        if (order.getUserId() == null) {
            throw new RuntimeException("用户ID不能为空");
        }
    }
}

// 执行流程(Savepoint机制):
// 1. 外层事务T1开始
// 2. 每个createSingleOrder()设置保存点
// 3. 内层方法异常 → 回滚到保存点
// 4. 外层事务继续执行后续订单
// 5. 最终T1提交或回滚

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】

关键特性

java

复制

下载

复制代码
// 1. 保存点机制
// 基于JDBC的Savepoint实现
Savepoint savepoint = connection.setSavepoint("nested_tx");
try {
    // 嵌套事务逻辑
    executeNestedOperation();
    connection.releaseSavepoint(savepoint);
} catch (Exception e) {
    connection.rollback(savepoint);  // 回滚到保存点
    throw e;
}

// 2. 部分提交
// 内层事务的提交是"部分提交"
// 最终提交依赖外层事务

// 3. 支持数据库
// MySQL的InnoDB支持保存点
// 部分数据库可能不支持NESTED传播行为

// 4. 与REQUIRES_NEW的区别
// NESTED: 共享连接,使用保存点
// REQUIRES_NEW: 新连接,完全独立

4. SUPPORTS(支持当前事务)

场景分析

java

复制

下载

复制代码
@Service
public class QueryService {
    
    // 查询服务通常不需要事务,但如果有事务就加入
    @Transactional(propagation = Propagation.SUPPORTS)
    public OrderDTO getOrderDetail(Long orderId) {
        // 复杂查询逻辑
        Order order = orderRepository.findById(orderId);
        User user = userRepository.findById(order.getUserId());
        
        return assembleOrderDTO(order, user);
    }
}

@Service
public class OrderService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateOrder(Order order) {
        // 更新前查询(加入当前事务)
        OrderDTO detail = queryService.getOrderDetail(order.getId());
        
        // 基于查询结果更新
        orderRepository.update(order);
        
        // 更新后查询(同一事务,看到更新结果)
        OrderDTO updated = queryService.getOrderDetail(order.getId());
    }
}

// 行为特点:
// 1. 在OrderService.updateOrder()中调用getOrderDetail()
//    → 加入REQUIRED事务,看到未提交的更新
// 2. 单独调用getOrderDetail()
//    → 无事务运行,查询已提交的数据

5. MANDATORY(强制要求事务)

场景分析

java

复制

下载

复制代码
@Service  
public class AuditService {
    
    // 审计操作必须在一个事务中执行
    @Transactional(propagation = Propagation.MANDATORY)
    public void auditOperation(OperationLog log) {
        // 审计逻辑必须看到完整的事务视图
        auditRepository.save(log);
    }
}

@Service
public class UserService {
    
    // 正确的调用方式
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateUser(User user) {
        userRepository.update(user);
        
        // 在事务内调用审计
        auditService.auditOperation(buildAuditLog(user));
    }
    
    // 错误的调用方式
    public void getUserInfo(Long userId) {
        User user = userRepository.findById(userId);
        
        // 这里没有事务,会抛出异常!
        auditService.auditOperation(buildAuditLog(user));
        // 抛出IllegalTransactionStateException
    }
}
设计意图

java

复制

下载

复制代码
// 1. 强制事务上下文
// 确保某些关键操作必须在事务保护下执行

// 2. 设计约束
// 防止开发人员无意中在非事务环境下调用关键方法

// 3. 使用场景
// 审计日志、重要数据修改、资金操作

6. NOT_SUPPORTED(非事务执行)

场景分析

java

复制

下载

复制代码
@Service
public class FileService {
    
    // 文件操作通常不需要事务
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void uploadFile(MultipartFile file) {
        // 文件存储逻辑(非事务)
        String path = fileStorage.save(file);
        
        // 记录元数据(可能需要事务)
        fileMetadataService.saveMetadata(path, file.getSize());
    }
}

@Service  
public class TransactionalService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void businessProcess() {
        // 主事务逻辑
        businessRepository.save(data);
        
        // 调用非事务方法(当前事务被挂起)
        fileService.uploadFile(file);  // NOT_SUPPORTED
        
        // 恢复事务,继续执行
        businessRepository.update(data);
    }
}

// 关键点:
// 1. 当前有事务 → 挂起事务,非事务执行
// 2. 当前无事务 → 直接非事务执行
// 3. 挂起的事务在方法执行完后恢复
适用场景

java

复制

下载

复制代码
// 1. 耗时操作
// 避免长时间占用数据库连接
public void generateReport() {  // NOT_SUPPORTED
    // 复杂计算,耗时较长
    Report report = computeComplexReport();
    // 不占用事务连接
}

// 2. 外部系统调用
public void callExternalAPI() {  // NOT_SUPPORTED
    // HTTP调用外部服务
    ResponseEntity response = restTemplate.post(...);
    // 不受事务管理,失败不回滚
}

// 3. 文件/IO操作
public void processFile() {  // NOT_SUPPORTED
    // 读写文件系统
    Files.copy(source, target);
    // 文件操作不支持事务回滚
}

7. NEVER(禁止事务)

场景分析

java

复制

下载

复制代码
@Service
public class CacheService {
    
    // 缓存操作禁止在事务中执行
    @Transactional(propagation = Propagation.NEVER)
    public void updateCache(String key, Object value) {
        // 缓存更新应该立即生效
        redisTemplate.opsForValue().set(key, value);
        
        // 如果在事务中执行,缓存更新可能延迟
        // 导致缓存与数据库不一致
    }
}

@Service
public class UserService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateUserWithCache(User user) {
        // 更新数据库
        userRepository.update(user);
        
        // 错误:在事务中更新缓存
        // cacheService.updateCache("user:"+user.getId(), user);
        // 抛出IllegalTransactionStateException
    }
    
    public void updateUserWithoutCache(User user) {
        // 更新数据库(无事务)
        userRepository.update(user);
        
        // 正确:无事务时更新缓存
        cacheService.updateCache("user:"+user.getId(), user);
    }
}
设计哲学

java

复制

下载

复制代码
// 1. 强制分离
// 明确区分事务性操作和非事务性操作

// 2. 防止误用
// 避免在事务中执行不应该在事务中的操作

// 3. 性能考虑
// 确保某些操作不会受到事务开销影响

// 4. 一致性保证
// 防止缓存/外部系统与数据库状态不一致

三、实战场景与组合使用

场景1:订单支付流程

java

复制

下载

复制代码
@Service
public class PaymentService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public PaymentResult payOrder(PaymentRequest request) {
        // 1. 检查订单状态(加入事务)
        Order order = orderService.getOrder(request.getOrderId());
        
        // 2. 扣款(独立事务,支付必须提交)
        Payment payment = paymentGateway.deduct(request);  // REQUIRES_NEW
        
        // 3. 更新订单状态(当前事务)
        orderService.updateOrderStatus(order.getId(), OrderStatus.PAID);
        
        // 4. 记录支付日志(独立事务,失败不影响)
        try {
            paymentLogService.logPayment(payment);  // REQUIRES_NEW
        } catch (Exception e) {
            logger.error("支付日志记录失败", e);
        }
        
        // 5. 发送支付成功消息(独立事务)
        messageService.sendPaymentSuccess(payment);  // REQUIRES_NEW
        
        return buildResult(payment);
    }
}

@Service
public class PaymentGatewayService {
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Payment deduct(PaymentRequest request) {
        // 第三方支付调用
        ThirdPartyResponse response = callPaymentAPI(request);
        
        // 本地支付记录
        Payment payment = savePaymentRecord(response);
        
        // 支付必须独立提交,即使后续步骤失败
        return payment;
    }
}

场景2:批量数据处理

java

复制

下载

复制代码
@Service
public class BatchDataProcessor {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void processBatch(List<DataItem> items) {
        int successCount = 0;
        int failCount = 0;
        
        for (DataItem item : items) {
            try {
                // 每个item独立处理,失败不影响其他
                processSingleItem(item);  // NESTED
                successCount++;
            } catch (Exception e) {
                failCount++;
                errorHandler.handleError(item, e);
            }
        }
        
        // 记录处理统计(独立事务)
        statisticService.recordProcessResult(
            successCount, failCount);  // REQUIRES_NEW
        
        // 如果整体失败率过高,回滚整个批处理
        if (failCount > items.size() * 0.3) {
            throw new BatchProcessException("失败率过高");
        }
    }
    
    @Transactional(propagation = Propagation.NESTED)
    public void processSingleItem(DataItem item) {
        // 复杂的数据处理逻辑
        validate(item);
        transform(item);
        persist(item);
    }
}

场景3:缓存与数据库同步

java

复制

下载

复制代码
@Service
public class UserService {
    
    // 主业务方法 - 使用事务
    @Transactional(propagation = Propagation.REQUIRED)
    public User updateUser(User user) {
        // 1. 更新数据库
        User updated = userRepository.save(user);
        
        // 2. 更新缓存(必须无事务)
        // 使用编程式事务管理
        TransactionTemplate transactionTemplate = 
            new TransactionTemplate(transactionManager);
        transactionTemplate.setPropagationBehavior(
            Propagation.NOT_SUPPORTED.value());
        
        transactionTemplate.execute(status -> {
            cacheService.updateUserCache(updated);
            return null;
        });
        
        return updated;
    }
    
    // 查询方法 - 根据情况决定是否使用事务
    @Transactional(propagation = Propagation.SUPPORTS)
    public User getUser(Long userId) {
        // 先查缓存
        User cached = cacheService.getUserFromCache(userId);
        if (cached != null) {
            return cached;
        }
        
        // 查数据库
        User user = userRepository.findById(userId);
        
        // 异步更新缓存(无事务)
        cacheService.asyncUpdateCache(userId, user);
        
        return user;
    }
}

四、源码实现解析

1. 传播行为处理入口

java

复制

下载

复制代码
// AbstractPlatformTransactionManager
public final TransactionStatus getTransaction(
        @Nullable TransactionDefinition definition) {
    
    // 获取当前事务
    Object transaction = doGetTransaction();
    
    // 检查当前是否存在事务
    boolean existing = isExistingTransaction(transaction);
    
    // 根据传播行为处理
    if (definition.getPropagationBehavior() == 
            TransactionDefinition.PROPAGATION_REQUIRED) {
        
        if (existing) {
            // 存在事务 → 加入
            return handleExistingTransaction(definition, transaction, existing);
        }
        // 不存在事务 → 新建
        return startTransaction(definition, transaction, debugEnabled, null);
    }
    
    if (definition.getPropagationBehavior() == 
            TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
        
        // 挂起当前事务(如果存在)
        SuspendedResourcesHolder suspended = null;
        if (existing) {
            suspended = suspend(transaction);
        }
        
        // 创建新事务
        return startTransaction(definition, transaction, debugEnabled, suspended);
    }
    
    // ... 其他传播行为的处理
}

2. REQUIRES_NEW实现细节

java

复制

下载

复制代码
// DataSourceTransactionManager
protected Object doSuspend(Object transaction) {
    DataSourceTransactionObject txObject = 
        (DataSourceTransactionObject) transaction;
    
    // 释放当前连接
    txObject.setConnectionHolder(null);
    
    // 从ThreadLocal中解绑连接
    return TransactionSynchronizationManager.unbindResource(this.dataSource);
}

protected void doResume(@Nullable Object transaction, 
        Object suspendedResources) {
    
    // 重新绑定连接到ThreadLocal
    TransactionSynchronizationManager.bindResource(
        this.dataSource, suspendedResources);
}

3. NESTED实现细节

java

复制

下载

复制代码
// DataSourceTransactionManager (JDBC实现)
protected void doBegin(Object transaction, TransactionDefinition definition) {
    DataSourceTransactionObject txObject = 
        (DataSourceTransactionObject) transaction;
    
    Connection con = txObject.getConnectionHolder().getConnection();
    
    if (definition.getPropagationBehavior() == 
            TransactionDefinition.PROPAGATION_NESTED) {
        
        // 设置保存点
        if (this.savepointAllowed) {
            // 使用JDBC保存点
            Savepoint savepoint = con.setSavepoint();
            txObject.setSavepoint(savepoint);
        } else {
            // 不支持保存点则使用新事务(REQUIRES_NEW)
            // 实际上Spring会降级处理
        }
    }
    
    // ... 其他初始化逻辑
}

五、常见陷阱与最佳实践

⚠️ 常见陷阱

陷阱1:REQUIRES_NEW导致死锁

java

复制

下载

复制代码
// 错误示例
@Service
public class AccountService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void transfer(Account from, Account to, BigDecimal amount) {
        // 先扣款
        debit(from, amount);  // REQUIRES_NEW
        
        // 再存款(等待扣款事务提交)
        credit(to, amount);   // REQUIRES_NEW
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void debit(Account account, BigDecimal amount) {
        // 持有账户A锁
        account.setBalance(account.getBalance().subtract(amount));
        accountRepository.save(account);
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)  
    public void credit(Account account, BigDecimal amount) {
        // 等待账户B锁(可能被其他事务持有)
        account.setBalance(account.getBalance().add(amount));
        accountRepository.save(account);
    }
}
// 可能产生死锁:多个转账同时进行时
陷阱2:NESTED不支持时降级问题

java

复制

下载

复制代码
// 数据库不支持保存点时
@Service
public class BatchService {
    
    @Transactional
    public void batchProcess() {
        for (Data data : dataList) {
            // 如果数据库不支持NESTED,Spring会使用REQUIRED
            // 导致第一个失败后整个batch回滚
            processItem(data);  // 期望NESTED
        }
    }
    
    @Transactional(propagation = Propagation.NESTED)
    public void processItem(Data data) {
        // 处理逻辑
    }
}

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】

最佳实践

实践1:合理选择传播行为

java

复制

下载

复制代码
// 选择指南
public class PropagationSelectionGuide {
    
    // 1. 默认使用REQUIRED
    // 大多数业务方法
    @Transactional  // 默认就是REQUIRED
    public void businessMethod() {}
    
    // 2. 独立操作使用REQUIRES_NEW
    // 日志、消息、外部调用
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void independentOperation() {}
    
    // 3. 查询服务使用SUPPORTS
    // 复杂查询,可加入事务也可不加入
    @Transactional(propagation = Propagation.SUPPORTS)
    public QueryResult complexQuery() {}
    
    // 4. 必须事务时使用MANDATORY
    // 审计、关键数据修改
    @Transactional(propagation = Propagation.MANDATORY)
    public void criticalOperation() {}
    
    // 5. 禁止事务使用NEVER
    // 缓存操作、文件操作
    @Transactional(propagation = Propagation.NEVER)
    public void nonTransactionalOp() {}
}
实践2:传播行为与隔离级别配合

java

复制

下载

复制代码
@Service
public class FinancialService {
    
    // 财务操作:需要强一致性
    @Transactional(
        propagation = Propagation.REQUIRED,
        isolation = Isolation.SERIALIZABLE  // 最高隔离级别
    )
    public void financialTransfer() {
        // 资金转移逻辑
    }
    
    // 日志记录:可以接受脏读
    @Transactional(
        propagation = Propagation.REQUIRES_NEW,
        isolation = Isolation.READ_COMMITTED  // 较低隔离级别
    )
    public void auditLog() {
        // 审计日志记录
    }
    
    // 统计查询:可重复读
    @Transactional(
        propagation = Propagation.SUPPORTS,
        isolation = Isolation.REPEATABLE_READ
    )
    public Statistics generateReport() {
        // 报表生成
    }
}

六、面试深度问题

1. 源码级问题

java

复制

下载

复制代码
// Q1: Spring如何实现事务传播?
// A: 通过AbstractPlatformTransactionManager的getTransaction方法,
//    根据当前事务状态和传播行为决定是加入、新建还是挂起事务。

// Q2: REQUIRES_NEW是如何挂起和恢复事务的?
// A: 1. suspend()方法:解绑当前线程的资源(如数据库连接)
//    2. 开始新事务,使用新的连接
//    3. resume()方法:重新绑定之前挂起的资源

// Q3: NESTED在MySQL和Oracle中的实现差异?
// A: MySQL(InnoDB): 使用SAVEPOINT实现
//    Oracle: 原生支持嵌套事务
//    不支持SAVEPOINT的数据库会降级为REQUIRED

2. 场景设计问题

java

复制

下载

复制代码
// Q1: 设计一个需要部分提交的批量处理系统
// 要求:单个失败不影响整体,但失败过多需要回滚

// 解决方案:
@Transactional
public void batchProcess() {
    for (Item item : items) {
        try {
            // 使用NESTED实现部分提交
            processItemWithSavepoint(item);
        } catch (Exception e) {
            handleError(item, e);
        }
    }
}

@Transactional(propagation = Propagation.NESTED)
public void processItemWithSavepoint(Item item) {
    // 业务逻辑
}

3. 性能优化问题

java

复制

下载

复制代码
// Q1: 大量使用REQUIRES_NEW有什么性能影响?
// A: 1. 频繁创建/提交事务开销
//    2. 数据库连接数增加
//    3. 锁竞争可能加剧
//    优化:批量操作、连接池调优

// Q2: 如何监控事务传播行为的影响?
// A: 1. 使用Spring的TransactionSynchronization
//    2. 监控事务创建/提交/回滚次数
//    3. 跟踪事务执行时间
//    4. 分析死锁和锁等待

七、总结对比表

传播行为对比矩阵

传播行为 存在事务 不存在事务 异常回滚影响 适用场景
REQUIRED 加入 新建 全部回滚 默认选择,业务主流程
SUPPORTS 加入 非事务 看情况 查询服务,可事务可非事务
MANDATORY 加入 抛异常 全部回滚 必须事务的操作(审计)
REQUIRES_NEW 挂起后新建 新建 独立回滚 独立操作(日志、消息)
NOT_SUPPORTED 挂起后非事务 非事务 不影响事务 非事务操作(文件、缓存)
NEVER 抛异常 非事务 无影响 禁止事务(缓存更新)
NESTED 嵌套事务 新建 部分回滚 批量处理,部分提交

选择决策树

text

复制

下载

复制代码
需要事务吗?
├── 是 → 当前有事务吗?
│   ├── 是 → 需要独立提交吗?
│   │   ├── 是 → REQUIRES_NEW(完全独立)
│   │   └── 否 → 需要部分提交吗?
│   │       ├── 是 → NESTED(支持保存点)
│   │       └── 否 → REQUIRED(默认加入)
│   └── 否 → REQUIRED(新建事务)
└── 否 → 禁止事务吗?
    ├── 是 → NEVER(强制非事务)
    └── 否 → 有事务就加入吗?
        ├── 是 → SUPPORTS(支持事务)
        └── 否 → NOT_SUPPORTED(非事务)

记住 :传播行为的选择本质是事务边界和异常处理策略的设计。理解每种行为背后的设计意图,才能在实际业务中做出合理的选择。

相关推荐
winfield8212 小时前
GC 日志全解析:格式规范 + 问题分析 + 性能优化
java·jvm
甜可儿2 小时前
mac环境安装不同版本maven
java·macos·maven
毕设源码-朱学姐2 小时前
【开题答辩全过程】以 基于SpringBoot的智慧商城系统设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
七夜zippoe2 小时前
Spring Boot自动配置魔法与@EnableAutoConfiguration原理揭秘
java·spring boot·后端·自动配置·条件注解
逍遥德2 小时前
mysql-8.4.7-winx64.zip 安装/运行
数据库·mysql
就叫飞六吧2 小时前
钉钉企业内部应用 SSO 免登集成实战 (Spring Boot 版)
java·spring boot·钉钉
秋邱2 小时前
Java包装类:基本类型与包装类转换、自动装箱与拆箱原理
java·开发语言·python
lkbhua莱克瓦242 小时前
基础-约束
android·开发语言·数据库·笔记·sql·mysql·约束
falldeep2 小时前
LeetCode高频SQL50题总结
数据结构·数据库·sql·算法·leetcode·职场和发展