Spring 事务全面详解

Spring 事务全面详解

一、事务基础概念

1.1 什么是事务?

事务是一组要么全部成功、要么全部失败的数据库操作单元。它有四大特性(ACID):

java 复制代码
// ACID 特性示例
public class TransactionACID {
    // 1. Atomicity(原子性):事务不可分割
    @Transactional
    public void transferMoney(Account from, Account to, BigDecimal amount) {
        // 要么两个操作都成功,要么都失败
        from.withdraw(amount);  // 扣款
        to.deposit(amount);     // 存款
    }
    
    // 2. Consistency(一致性):数据始终保持有效状态
    // 转账前后,总金额保持不变
    
    // 3. Isolation(隔离性):事务间互不干扰
    // 多个转账操作同时进行,互相不影响
    
    // 4. Durability(持久性):事务提交后永久保存
    // 转账成功后,数据永久存储
}

1.2 Spring 事务的作用

Spring 事务管理提供了:

  • 声明式事务:通过注解配置
  • 编程式事务:通过代码控制
  • 统一抽象:支持多种数据访问技术(JDBC、JPA、Hibernate等)

二、Spring 事务的核心接口

2.1 关键接口关系

classDiagram class PlatformTransactionManager { <> +getTransaction(TransactionDefinition): TransactionStatus +commit(TransactionStatus): void +rollback(TransactionStatus): void } class TransactionDefinition { <> +PROPAGATION_REQUIRED +PROPAGATION_REQUIRES_NEW +getIsolationLevel() +getTimeout() +isReadOnly() } class TransactionStatus { <> +isNewTransaction() +hasSavepoint() +setRollbackOnly() +isRollbackOnly() } PlatformTransactionManager <|-- DataSourceTransactionManager PlatformTransactionManager <|-- JpaTransactionManager PlatformTransactionManager <|-- HibernateTransactionManager DataSourceTransactionManager : +JDBC事务 JpaTransactionManager : +JPA事务 HibernateTransactionManager : +Hibernate事务

2.2 主要实现类

java 复制代码
// 1. JDBC 事务管理器
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

// 2. JPA 事务管理器
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
    return new JpaTransactionManager(emf);
}

// 3. Hibernate 事务管理器
@Bean
public PlatformTransactionManager transactionManager(SessionFactory sessionFactory) {
    return new HibernateTransactionManager(sessionFactory);
}

三、事务的传播行为(Propagation)

3.1 七种传播行为详解

java 复制代码
@Service
public class PropagationService {
    
    // 1. REQUIRED(默认):如果当前有事务,则加入;否则新建事务
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 有事务则加入,没有则新建
    }
    
    // 2. REQUIRES_NEW:总是新建事务,挂起当前事务(如果有)
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB() {
        // 总是新建独立事务
        // 外层事务回滚不影响这里,这里回滚也不影响外层
    }
    
    // 3. SUPPORTS:如果当前有事务,则加入;否则非事务运行
    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodC() {
        // 查询方法常用,有事务用事务,没事务直接查
    }
    
    // 4. NOT_SUPPORTED:非事务运行,挂起当前事务(如果有)
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void methodD() {
        // 强制非事务执行
        // 适用于不需要事务的批量操作
    }
    
    // 5. MANDATORY:必须存在事务,否则抛异常
    @Transactional(propagation = Propagation.MANDATORY)
    public void methodE() {
        // 必须在事务中调用,否则 IllegalTransactionStateException
    }
    
    // 6. NEVER:必须非事务运行,否则抛异常
    @Transactional(propagation = Propagation.NEVER)
    public void methodF() {
        // 必须在非事务中调用
    }
    
    // 7. NESTED:嵌套事务,保存点机制
    @Transactional(propagation = Propagation.NESTED)
    public void methodG() {
        // 嵌套子事务
        // 外层回滚,内层一定回滚
        // 内层回滚,外层可以选择捕获异常继续
    }
}

3.2 传播行为嵌套示例

java 复制代码
@Service
@Slf4j
public class NestedTransactionService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void outerMethod() {
        log.info("外层事务开始");
        
        userRepository.save(new User("张三"));
        
        try {
            innerMethodRequiresNew();  // 独立事务
        } catch (Exception e) {
            log.error("内层异常被捕获", e);
        }
        
        try {
            innerMethodNested();      // 嵌套事务
        } catch (Exception e) {
            log.error("嵌套异常被捕获", e);
        }
        
        userRepository.save(new User("李四"));
        log.info("外层事务结束");
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void innerMethodRequiresNew() {
        log.info("REQUIRES_NEW 事务开始");
        userRepository.save(new User("王五"));
        throw new RuntimeException("REQUIRES_NEW 失败");
        // 异常不会影响外层事务
    }
    
    @Transactional(propagation = Propagation.NESTED)
    public void innerMethodNested() {
        log.info("NESTED 事务开始");
        userRepository.save(new User("赵六"));
        throw new RuntimeException("NESTED 失败");
        // 外层可以回滚到保存点
    }
}

四、事务的隔离级别(Isolation)

4.1 四种隔离级别

java 复制代码
@Service
public class IsolationService {
    
    // 1. READ_UNCOMMITTED(读未提交)- 最低级别
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void readUncommitted() {
        // 可能读到其他事务未提交的数据(脏读)
    }
    
    // 2. READ_COMMITTED(读已提交)- 默认级别
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void readCommitted() {
        // 只能读到已提交的数据
        // 但可能出现不可重复读问题
    }
    
    // 3. REPEATABLE_READ(可重复读)- MySQL 默认
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void repeatableRead() {
        // 同一事务中多次读取结果一致
        // 但可能出现幻读问题
    }
    
    // 4. SERIALIZABLE(串行化)- 最高级别
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void serializable() {
        // 完全串行执行,性能最差
    }
}

4.2 隔离问题演示

java 复制代码
@Service
@Slf4j
public class IsolationProblemDemo {
    
    // 脏读问题:读到未提交的数据
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void dirtyReadProblem() {
        // 事务A修改数据但未提交
        // 事务B能读到A未提交的数据
        // 如果A回滚,B读到的就是脏数据
    }
    
    // 不可重复读问题:同一事务中两次读取结果不同
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void nonRepeatableReadProblem() {
        User user1 = userRepository.findById(1L);  // 第一次读取
        
        // 另一个事务修改并提交了数据
        
        User user2 = userRepository.findById(1L);  // 第二次读取
        // user1 和 user2 可能不同!
    }
    
    // 幻读问题:同一查询条件返回不同行数
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void phantomReadProblem() {
        List<User> list1 = userRepository.findByName("张三");  // 返回2条
        
        // 另一个事务插入了一条 name="张三" 的记录并提交
        
        List<User> list2 = userRepository.findByName("张三");  // 返回3条!
        // 行数变了!
    }
}

五、Spring 事务的实现原理

5.1 AOP 代理机制

java 复制代码
// Spring 创建代理对象的伪代码
public class TransactionProxyCreator {
    
    public Object createProxy(Object target) {
        return Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            new TransactionInterceptor(target)  // 事务拦截器
        );
    }
}

// 事务拦截器
class TransactionInterceptor implements InvocationHandler {
    private Object target;
    private PlatformTransactionManager transactionManager;
    
    public Object invoke(Object proxy, Method method, Object[] args) {
        // 1. 检查方法是否有 @Transactional
        if (!hasTransactionalAnnotation(method)) {
            return method.invoke(target, args);  // 直接执行
        }
        
        // 2. 开启事务
        TransactionStatus status = transactionManager.getTransaction(
            getTransactionDefinition(method)
        );
        
        try {
            // 3. 执行业务方法
            Object result = method.invoke(target, args);
            
            // 4. 提交事务
            transactionManager.commit(status);
            return result;
            
        } catch (Exception e) {
            // 5. 回滚事务
            transactionManager.rollback(status);
            throw e;
        }
    }
}

5.2 自调用问题详解

java 复制代码
@Service
public class SelfInvocationService {
    
    // 情况1:自调用,事务不生效
    @Transactional
    public void methodA() {
        System.out.println("methodA 事务: " + 
            TransactionSynchronizationManager.getCurrentTransactionName());
        
        this.methodB();  // ❌ 直接调用,绕过代理
        
        // 输出:methodB 事务: null(没有事务!)
    }
    
    @Transactional
    public void methodB() {
        System.out.println("methodB 事务: " + 
            TransactionSynchronizationManager.getCurrentTransactionName());
    }
    
    // 情况2:通过代理调用,事务生效
    @Autowired
    @Lazy
    private SelfInvocationService selfProxy;
    
    @Transactional
    public void methodC() {
        System.out.println("methodC 事务: " + 
            TransactionSynchronizationManager.getCurrentTransactionName());
        
        selfProxy.methodD();  // ✅ 通过代理调用
        
        // 输出:methodD 事务: xxx(有事务!)
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodD() {
        System.out.println("methodD 事务: " + 
            TransactionSynchronizationManager.getCurrentTransactionName());
    }
}

5.3 事务同步管理器

java 复制代码
// TransactionSynchronizationManager 关键方法
public abstract class TransactionSynchronizationManager {
    
    // 当前线程的事务状态
    private static final ThreadLocal<Map<Object, Object>> resources = 
        new NamedThreadLocal<>("Transactional resources");
    
    // 当前事务名称
    private static final ThreadLocal<String> currentTransactionName = 
        new NamedThreadLocal<>("Current transaction name");
    
    // 是否只读
    private static final ThreadLocal<Boolean> currentTransactionReadOnly = 
        new NamedThreadLocal<>("Current transaction read-only status");
    
    // 隔离级别
    private static final ThreadLocal<Integer> currentTransactionIsolationLevel = 
        new NamedThreadLocal<>("Current transaction isolation level");
    
    // 是否实际有事务
    private static final ThreadLocal<Boolean> actualTransactionActive = 
        new NamedThreadLocal<>("Actual transaction active");
}

六、声明式事务配置

6.1 注解配置

java 复制代码
// 完整的 @Transactional 注解使用
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
    
    // 事务管理器 Bean 名称
    String value() default "";
    String transactionManager() default "";
    
    // 传播行为
    Propagation propagation() default Propagation.REQUIRED;
    
    // 隔离级别
    Isolation isolation() default Isolation.DEFAULT;
    
    // 超时时间(秒)
    int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
    
    // 是否只读
    boolean readOnly() default false;
    
    // 哪些异常回滚
    Class<? extends Throwable>[] rollbackFor() default {};
    String[] rollbackForClassName() default {};
    
    // 哪些异常不回滚
    Class<? extends Throwable>[] noRollbackFor() default {};
    String[] noRollbackForClassName() default {};
}

6.2 XML 配置

xml 复制代码
<!-- XML 配置方式 -->
<beans>
    <!-- 1. 配置事务管理器 -->
    <bean id="transactionManager" 
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!-- 2. 配置事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 查询方法:只读 -->
            <tx:method name="get*" read-only="true" propagation="SUPPORTS"/>
            <tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
            <tx:method name="query*" read-only="true" propagation="SUPPORTS"/>
            
            <!-- 增删改方法:需要事务 -->
            <tx:method name="save*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="delete*" propagation="REQUIRED"/>
            <tx:method name="insert*" propagation="REQUIRED"/>
            
            <!-- 其他方法:默认配置 -->
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    
    <!-- 3. 配置 AOP -->
    <aop:config>
        <aop:pointcut id="serviceOperation" 
                      expression="execution(* com.example.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
    </aop:config>
</beans>

6.3 Java 配置

java 复制代码
@Configuration
@EnableTransactionManagement  // 启用事务管理
public class TransactionConfig {
    
    // 配置事务管理器
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
    
    // 配置事务通知(编程式)
    @Bean
    public TransactionInterceptor transactionInterceptor(
            PlatformTransactionManager transactionManager) {
        
        NameMatchTransactionAttributeSource source = 
            new NameMatchTransactionAttributeSource();
        
        RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
        readOnlyTx.setReadOnly(true);
        readOnlyTx.setPropagationBehavior(Propagation.SUPPORTS.value());
        
        RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
        requiredTx.setRollbackRules(
            Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        requiredTx.setPropagationBehavior(Propagation.REQUIRED.value());
        requiredTx.setTimeout(5);  // 5秒超时
        
        // 方法名匹配规则
        Map<String, TransactionAttribute> txMap = new HashMap<>();
        txMap.put("get*", readOnlyTx);
        txMap.put("find*", readOnlyTx);
        txMap.put("save*", requiredTx);
        txMap.put("update*", requiredTx);
        txMap.put("delete*", requiredTx);
        
        source.setNameMap(txMap);
        
        return new TransactionInterceptor(transactionManager, source);
    }
    
    // 配置 AOP
    @Bean
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
            TransactionInterceptor transactionInterceptor) {
        
        BeanFactoryTransactionAttributeSourceAdvisor advisor = 
            new BeanFactoryTransactionAttributeSourceAdvisor();
        advisor.setTransactionInterceptor(transactionInterceptor);
        
        return advisor;
    }
}

七、编程式事务

7.1 TransactionTemplate

java 复制代码
@Service
public class ProgrammaticTransactionService {
    
    private final TransactionTemplate transactionTemplate;
    private final UserRepository userRepository;
    
    public ProgrammaticTransactionService(
            PlatformTransactionManager transactionManager,
            UserRepository userRepository) {
        
        this.transactionTemplate = new TransactionTemplate(transactionManager);
        this.userRepository = userRepository;
        
        // 配置 TransactionTemplate
        transactionTemplate.setPropagationBehavior(Propagation.REQUIRED.value());
        transactionTemplate.setIsolationLevel(Isolation.READ_COMMITTED.value());
        transactionTemplate.setTimeout(30);  // 30秒
        transactionTemplate.setReadOnly(false);
    }
    
    // 使用 TransactionTemplate
    public void createUsers(List<User> users) {
        // 方式1:使用 TransactionCallback
        List<String> ids = transactionTemplate.execute(status -> {
            List<String> result = new ArrayList<>();
            
            for (User user : users) {
                userRepository.save(user);
                result.add(user.getId());
                
                // 可以设置保存点
                if (users.indexOf(user) == 5) {
                    Object savepoint = status.createSavepoint();
                    try {
                        // 可能失败的操作
                        riskyOperation();
                    } catch (Exception e) {
                        status.rollbackToSavepoint(savepoint);  // 回滚到保存点
                    }
                }
            }
            
            return result;
        });
        
        // 方式2:使用 TransactionCallbackWithoutResult
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                for (User user : users) {
                    userRepository.save(user);
                    
                    // 可以手动回滚
                    if (user.getName().equals("invalid")) {
                        status.setRollbackOnly();  // 标记为只回滚
                    }
                }
            }
        });
    }
}

7.2 PlatformTransactionManager 直接使用

java 复制代码
@Service
public class PlatformTransactionManagerService {
    
    private final PlatformTransactionManager transactionManager;
    private final UserRepository userRepository;
    
    public void complexTransaction() {
        // 1. 定义事务属性
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        definition.setPropagationBehavior(Propagation.REQUIRED.value());
        definition.setIsolationLevel(Isolation.READ_COMMITTED.value());
        definition.setTimeout(30);
        definition.setReadOnly(false);
        definition.setName("complexTransaction");
        
        // 2. 开启事务
        TransactionStatus status = transactionManager.getTransaction(definition);
        
        try {
            // 3. 执行业务逻辑
            userRepository.save(new User("张三"));
            
            // 嵌套事务
            DefaultTransactionDefinition nestedDef = new DefaultTransactionDefinition();
            nestedDef.setPropagationBehavior(Propagation.NESTED.value());
            TransactionStatus nestedStatus = transactionManager.getTransaction(nestedDef);
            
            try {
                userRepository.save(new User("李四"));
                transactionManager.commit(nestedStatus);  // 提交嵌套事务
            } catch (Exception e) {
                transactionManager.rollback(nestedStatus);  // 回滚嵌套事务
                throw e;
            }
            
            // 4. 提交主事务
            transactionManager.commit(status);
            
        } catch (Exception e) {
            // 5. 回滚主事务
            transactionManager.rollback(status);
            throw e;
        }
    }
}

八、常见问题与解决方案

8.1 事务失效的 8 种情况

java 复制代码
@Service
public class TransactionFailureDemo {
    
    // 1. 非 public 方法 ❌
    @Transactional
    private void privateMethod() {
        // 事务不生效
    }
    
    // 2. 自调用 ❌
    @Transactional
    public void methodA() {
        this.methodB();  // 事务不生效
    }
    
    @Transactional
    public void methodB() { }
    
    // 3. 异常被捕获 ❌
    @Transactional
    public void methodC() {
        try {
            userRepository.save(user);
            throw new RuntimeException();
        } catch (Exception e) {
            // 异常被捕获,事务不会回滚
        }
    }
    
    // 4. 异常类型不匹配 ❌
    @Transactional(rollbackFor = RuntimeException.class)
    public void methodD() throws Exception {
        throw new Exception();  // 不是 RuntimeException,不会回滚
    }
    
    // 5. 多线程调用 ❌
    @Transactional
    public void methodE() {
        new Thread(() -> {
            userRepository.save(user);  // 新线程,事务不生效
        }).start();
    }
    
    // 6. 不支持事务的数据库 ❌
    // 如 MySQL 的 MyISAM 引擎
    
    // 7. 未启用事务管理 ❌
    // 缺少 @EnableTransactionManagement
    
    // 8. 方法内部 new 对象调用 ❌
    @Transactional
    public void methodF() {
        new InnerService().doSomething();  // 事务不传播
    }
    
    class InnerService {
        @Transactional
        public void doSomething() {
            // 事务不生效
        }
    }
}

8.2 解决方案

java 复制代码
@Service
public class TransactionSolution {
    
    // 方案1:自注入解决自调用
    @Autowired
    @Lazy
    private TransactionSolution selfProxy;
    
    public void methodA() {
        selfProxy.methodB();  // ✅ 通过代理调用
    }
    
    @Transactional
    public void methodB() { }
    
    // 方案2:正确抛出异常
    @Transactional
    public void methodC() {
        try {
            userRepository.save(user);
            throw new RuntimeException();
        } catch (Exception e) {
            // 1. 重新抛出运行时异常
            throw new RuntimeException(e);
            
            // 2. 或者设置回滚标记
            TransactionAspectSupport.currentTransactionStatus()
                .setRollbackOnly();
        }
    }
    
    // 方案3:使用编程式事务
    private final TransactionTemplate transactionTemplate;
    
    public void methodD() {
        transactionTemplate.execute(status -> {
            // 复杂的事务逻辑
            return null;
        });
    }
}

九、性能优化与最佳实践

9.1 事务优化建议

java 复制代码
@Service
public class TransactionOptimization {
    
    // 1. 合理设置只读事务
    @Transactional(readOnly = true)  // 查询优化
    public List<User> findAllActiveUsers() {
        return userRepository.findByActiveTrue();
    }
    
    // 2. 控制事务时间
    @Transactional(timeout = 5)  // 5秒超时
    public void batchProcess(List<Data> dataList) {
        // 分批处理,避免长事务
        int batchSize = 100;
        for (int i = 0; i < dataList.size(); i += batchSize) {
            processBatch(dataList.subList(i, Math.min(i + batchSize, dataList.size())));
        }
    }
    
    // 3. 合理使用传播行为
    @Transactional
    public void mainProcess() {
        // 主要业务
        userRepository.save(user);
        
        // 日志记录使用独立事务
        logService.saveLogAsync(user);  // REQUIRES_NEW
        
        // 发送消息使用非事务
        messageService.sendMessage(user);  // NOT_SUPPORTED
    }
    
    // 4. 避免大事务
    @Transactional
    public void bigTransaction() {
        // ❌ 不要在事务中做:
        // - 网络调用
        // - 文件IO
        // - 长时间计算
        // - 发送邮件/短信
        
        // ✅ 只做数据库操作
        userRepository.save(user);
        orderRepository.save(order);
    }
}

9.2 监控与调试

java 复制代码
@Component
public class TransactionMonitor {
    
    // 事务事件监听器
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
    public void handleAfterCompletion(TransactionCompletedEvent event) {
        System.out.println("事务完成: " + event);
    }
    
    // 自定义事务同步器
    public void withTransactionSync() {
        TransactionSynchronizationManager.registerSynchronization(
            new TransactionSynchronization() {
                @Override
                public void beforeCommit(boolean readOnly) {
                    System.out.println("事务提交前");
                }
                
                @Override
                public void afterCommit() {
                    System.out.println("事务提交后");
                }
                
                @Override
                public void afterCompletion(int status) {
                    System.out.println("事务完成,状态: " + 
                        (status == STATUS_COMMITTED ? "已提交" : "已回滚"));
                }
            }
        );
    }
    
    // 获取当前事务信息
    public void printTransactionInfo() {
        System.out.println("事务名称: " + 
            TransactionSynchronizationManager.getCurrentTransactionName());
        System.out.println("是否只读: " + 
            TransactionSynchronizationManager.isCurrentTransactionReadOnly());
        System.out.println("是否实际有事务: " + 
            TransactionSynchronizationManager.isActualTransactionActive());
        System.out.println("隔离级别: " + 
            TransactionSynchronizationManager.getCurrentTransactionIsolationLevel());
    }
}

十、实战案例

10.1 分布式事务(Seata)

java 复制代码
@Service
public class DistributedTransactionService {
    
    // 使用 Seata 的全局事务注解
    @GlobalTransactional  // Seata 全局事务
    @Transactional        // 本地事务
    public void placeOrder(Order order) {
        // 1. 扣减库存
        inventoryService.deduct(order.getProductId(), order.getQuantity());
        
        // 2. 创建订单
        orderService.create(order);
        
        // 3. 扣减余额
        accountService.deduct(order.getUserId(), order.getAmount());
        
        // 如果任何一步失败,所有操作都会回滚
    }
}

10.2 链式事务处理

java 复制代码
@Service
@Slf4j
public class ChainedTransactionService {
    
    private final TransactionTemplate transactionTemplate;
    private final UserRepository userRepository;
    private final OrderRepository orderRepository;
    
    public void processOrderChain(OrderRequest request) {
        // 步骤1:验证用户(独立事务)
        User user = transactionTemplate.execute(status -> {
            return userRepository.findById(request.getUserId())
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        });
        
        // 步骤2:创建订单(新事务)
        Order order = transactionTemplate.execute(status -> {
            Order newOrder = createOrder(request, user);
            return orderRepository.save(newOrder);
        });
        
        // 步骤3:扣减库存(可能失败)
        try {
            transactionTemplate.execute(status -> {
                deductInventory(order);
                return null;
            });
        } catch (Exception e) {
            log.error("库存扣减失败,回滚订单", e);
            // 回滚订单(新事务)
            transactionTemplate.execute(status -> {
                orderRepository.delete(order);
                return null;
            });
            throw e;
        }
        
        // 步骤4:发送通知(非事务)
        sendNotification(user, order);
    }
}

总结

Spring 事务的核心要点:

  1. 代理机制:Spring 通过 AOP 动态代理实现事务
  2. 自调用问题 :同一个类内部调用会绕过代理,导致 @Transactional 失效
  3. 传播行为:控制事务如何嵌套和传播
  4. 隔离级别:控制事务间的可见性和影响
  5. 声明式 vs 编程式:根据场景选择合适的控制方式
  6. 最佳实践:避免长事务、合理设置只读、及时释放资源

记住:Spring 事务是基于代理的,理解代理机制是掌握事务的关键

相关推荐
t***p9351 小时前
springboot项目读取 resources 目录下的文件的9种方式
java·spring boot·后端
哈哈哈笑什么1 小时前
微服务间进行调用进行失败后重试
后端
小周在成长1 小时前
Java 静态变量(Static Variables)指南
后端
加瓦点灯2 小时前
我用 AI,一天就把一个桌面提醒插件撸完了
后端
红色石头本尊2 小时前
27-集成swagger接口文档
后端
嘻哈baby2 小时前
Linux系统性能排查实战指南:从定位到解决
后端
开心就好20252 小时前
使用开心上架上架 App Store,一次跨平台团队的完整发布流程调度记录
后端
南囝coding2 小时前
《独立开发者精选工具》第 023 期
前端·后端·开源
文心快码BaiduComate2 小时前
Agent如何重塑跨角色协作的AI提效新范式
前端·后端·程序员