全部笔记All notes

Spring 事务管理完整指南

阅读 13m 12s13m 12s read

概述

Spring 事务管理 是 Spring 框架的核心功能之一,提供了一致的事务管理抽象,支持声明式和编程式事务管理。通过 AOP 技术,Spring 实现了对底层事务资源的统一管理,大大简化了事务编程的复杂性。

核心特性

  • 一致性事务抽象:统一不同事务管理器的接口
  • 声明式事务:通过注解或配置文件管理事务
  • 编程式事务:通过 API 显式控制事务
  • 多数据源支持:支持多种数据访问技术
  • 事务传播机制:灵活的事务传播策略
  • 异常处理:智能的事务回滚机制

应用场景

场景描述示例
数据库操作确保数据一致性转账操作、订单处理
批量处理保证批量操作的原子性数据导入、批量更新
分布式系统跨服务的事务一致性微服务间的数据同步
业务流程复杂业务逻辑的事务控制电商下单流程

💡 提示: 事务管理是确保数据一致性和完整性的关键机制,是企业级应用开发的基础。

事务基础理论

ACID 属性

事务必须具备以下四个属性:

1. 原子性(Atomicity)

事务是一个不可分割的工作单位,要么全部执行,要么全部不执行。

@Service
public class BankService {
    
    @Transactional
    public void transfer(String fromAccount, String toAccount, BigDecimal amount) {
        // 原子性:以下操作要么全部成功,要么全部失败
        accountDao.debit(fromAccount, amount);   // 扣款
        accountDao.credit(toAccount, amount);    // 加款
        transactionLogDao.log(fromAccount, toAccount, amount); // 记录日志
    }
}

2. 一致性(Consistency)

事务必须使数据库从一个一致性状态变换到另一个一致性状态。

@Service
public class OrderService {
    
    @Transactional
    public void createOrder(OrderDTO orderDTO) {
        // 一致性:业务规则得到维护
        
        // 检查库存(业务规则:库存必须充足)
        if (productService.getStock(orderDTO.getProductId()) < orderDTO.getQuantity()) {
            throw new InsufficientStockException("库存不足");
        }
        
        // 创建订单
        Order order = new Order(orderDTO);
        orderDao.save(order);
        
        // 扣减库存
        productService.reduceStock(orderDTO.getProductId(), orderDTO.getQuantity());
        
        // 更新用户积分
        userService.addPoints(orderDTO.getUserId(), order.getAmount().multiply(new BigDecimal("0.01")));
    }
}

3. 隔离性(Isolation)

多个事务并发执行时,一个事务的执行不应影响其他事务。

@Service
public class ConcurrentService {
    
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void handleConcurrentOperation(Long id) {
        // 隔离性:多个事务并发执行时相互隔离
        Account account = accountDao.findById(id);
        
        // 业务逻辑处理
        BigDecimal newBalance = account.getBalance().add(new BigDecimal("100"));
        account.setBalance(newBalance);
        
        accountDao.update(account);
    }
}

4. 持久性(Durability)

事务一旦提交,对数据库的改变是永久性的。

@Service
public class PaymentService {
    
    @Transactional
    public PaymentResult processPayment(PaymentRequest request) {
        // 持久性:提交后的数据变更是永久的
        
        Payment payment = new Payment(request);
        paymentDao.save(payment);
        
        // 更新账户余额
        accountService.updateBalance(request.getAccountId(), request.getAmount());
        
        // 发送通知(即使系统重启,支付记录也不会丢失)
        notificationService.sendPaymentNotification(payment);
        
        return new PaymentResult(payment.getId(), PaymentStatus.SUCCESS);
    }
}

事务并发问题

1. 脏读(Dirty Read)

一个事务读取了另一个事务未提交的数据。

// 事务A
@Transactional
public void transferMoney() {
    account.setBalance(1000);  // 更新但未提交
    // ... 其他操作
}

// 事务B
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void readBalance() {
    BigDecimal balance = account.getBalance(); // 可能读到1000(脏读)
    // 如果事务A回滚,这里读到的就是脏数据
}

2. 不可重复读(Non-Repeatable Read)

在同一事务中,多次读取同一数据返回的结果不一致。

@Transactional(isolation = Isolation.READ_COMMITTED)
public void demonstrateNonRepeatableRead() {
    // 第一次读取
    Account account1 = accountDao.findById(1L);
    System.out.println("第一次读取余额:" + account1.getBalance());
    
    // 此时其他事务修改了账户余额并提交
    
    // 第二次读取
    Account account2 = accountDao.findById(1L);
    System.out.println("第二次读取余额:" + account2.getBalance());
    
    // 两次读取结果不一致
}

3. 幻读(Phantom Read)

在同一事务中,多次执行相同查询返回不同的结果集。

@Transactional(isolation = Isolation.REPEATABLE_READ)
public void demonstratePhantomRead() {
    // 第一次查询
    List<Account> accounts1 = accountDao.findByBalanceGreaterThan(new BigDecimal("1000"));
    System.out.println("第一次查询账户数量:" + accounts1.size());
    
    // 此时其他事务插入了新的符合条件的账户
    
    // 第二次查询
    List<Account> accounts2 = accountDao.findByBalanceGreaterThan(new BigDecimal("1000"));
    System.out.println("第二次查询账户数量:" + accounts2.size());
    
    // 查询结果集不一致(出现了"幻影"记录)
}

Spring事务架构

核心组件

1. PlatformTransactionManager

事务管理器是 Spring 事务管理的核心接口。

public interface PlatformTransactionManager {
    
    /**
     * 开启事务
     */
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    
    /**
     * 提交事务
     */
    void commit(TransactionStatus status) throws TransactionException;
    
    /**
     * 回滚事务
     */
    void rollback(TransactionStatus status) throws TransactionException;
}

2. 常用事务管理器实现

@Configuration
@EnableTransactionManagement
public class TransactionConfig {
    
    /**
     * JDBC 事务管理器
     */
    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
    
    /**
     * JPA 事务管理器
     */
    @Bean
    public JpaTransactionManager jpaTransactionManager(EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
    
    /**
     * Hibernate 事务管理器
     */
    @Bean
    public HibernateTransactionManager hibernateTransactionManager(SessionFactory sessionFactory) {
        return new HibernateTransactionManager(sessionFactory);
    }
    
    /**
     * JTA 事务管理器(分布式事务)
     */
    @Bean
    public JtaTransactionManager jtaTransactionManager() {
        return new JtaTransactionManager();
    }
}

3. TransactionDefinition

事务定义包含事务的各种属性。

public class CustomTransactionDefinition implements TransactionDefinition {
    
    private int propagationBehavior = PROPAGATION_REQUIRED;
    private int isolationLevel = ISOLATION_DEFAULT;
    private int timeout = TIMEOUT_DEFAULT;
    private boolean readOnly = false;
    private String name;
    
    // 构造函数和getter/setter方法
    public CustomTransactionDefinition(String name) {
        this.name = name;
    }
    
    @Override
    public int getPropagationBehavior() {
        return this.propagationBehavior;
    }
    
    @Override
    public int getIsolationLevel() {
        return this.isolationLevel;
    }
    
    @Override
    public int getTimeout() {
        return this.timeout;
    }
    
    @Override
    public boolean isReadOnly() {
        return this.readOnly;
    }
    
    @Override
    public String getName() {
        return this.name;
    }
}

4. TransactionStatus

事务状态提供了事务的运行时信息。

public class TransactionStatusDemo {
    
    public void demonstrateTransactionStatus(TransactionStatus status) {
        // 检查事务状态
        System.out.println("是否为新事务: " + status.isNewTransaction());
        System.out.println("是否有保存点: " + status.hasSavepoint());
        System.out.println("是否为只读事务: " + status.isReadOnly());
        System.out.println("是否已完成: " + status.isCompleted());
        
        // 设置回滚标记
        if (someCondition()) {
            status.setRollbackOnly();
            System.out.println("事务被标记为回滚");
        }
        
        // 检查是否被标记为回滚
        if (status.isRollbackOnly()) {
            System.out.println("事务将被回滚");
        }
    }
    
    private boolean someCondition() {
        // 业务逻辑判断
        return true;
    }
}

声明式事务

基于注解的事务管理

1. 基础用法

@Service
@Transactional(readOnly = true) // 类级别默认事务属性
public class UserService {
    
    @Autowired
    private UserDao userDao;
    
    @Autowired
    private EmailService emailService;
    
    /**
     * 查询用户(只读事务)
     */
    public User findById(Long id) {
        return userDao.findById(id);
    }
    
    /**
     * 保存用户(读写事务)
     */
    @Transactional(readOnly = false, propagation = Propagation.REQUIRED)
    public User save(User user) {
        // 验证用户数据
        validateUser(user);
        
        // 保存用户
        User savedUser = userDao.save(user);
        
        // 发送欢迎邮件
        emailService.sendWelcomeEmail(savedUser.getEmail());
        
        return savedUser;
    }
    
    /**
     * 批量保存用户
     */
    @Transactional(
        propagation = Propagation.REQUIRED,
        isolation = Isolation.READ_COMMITTED,
        timeout = 30,
        rollbackFor = {Exception.class}
    )
    public void batchSave(List<User> users) {
        for (User user : users) {
            validateUser(user);
            userDao.save(user);
        }
    }
    
    private void validateUser(User user) {
        if (user.getEmail() == null || user.getEmail().trim().isEmpty()) {
            throw new IllegalArgumentException("邮箱不能为空");
        }
        if (userDao.existsByEmail(user.getEmail())) {
            throw new IllegalStateException("邮箱已存在");
        }
    }
}

2. 高级配置

@Service
public class AdvancedTransactionService {
    
    /**
     * 只读事务,优化性能
     */
    @Transactional(
        readOnly = true,
        timeout = 10,
        isolation = Isolation.READ_COMMITTED
    )
    public List<Order> getOrdersByUserId(Long userId) {
        return orderDao.findByUserId(userId);
    }
    
    /**
     * 需要新事务的操作
     */
    @Transactional(
        propagation = Propagation.REQUIRES_NEW,
        isolation = Isolation.SERIALIZABLE
    )
    public void createAuditLog(String operation, String details) {
        AuditLog log = new AuditLog(operation, details);
        auditLogDao.save(log);
    }
    
    /**
     * 不支持事务的操作
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void sendNotification(String message) {
        // 发送通知不需要事务
        notificationService.send(message);
    }
    
    /**
     * 嵌套事务示例
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void processOrderWithNestedTransaction(Order order) {
        // 主事务:处理订单
        orderDao.save(order);
        
        try {
            // 嵌套事务:发送通知
            sendOrderNotification(order);
        } catch (Exception e) {
            // 嵌套事务失败不影响主事务
            logger.error("发送订单通知失败", e);
        }
        
        // 继续主事务的其他操作
        updateInventory(order);
    }
    
    @Transactional(propagation = Propagation.NESTED)
    private void sendOrderNotification(Order order) {
        // 这是一个嵌套事务
        notificationService.sendOrderCreatedNotification(order);
    }
}

基于XML的事务配置

1. 传统XML配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <!-- 配置数据源 -->
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/testdb"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>
    
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!-- 配置事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 查询方法:只读事务 -->
            <tx:method name="get*" read-only="true" timeout="10"/>
            <tx:method name="find*" read-only="true" timeout="10"/>
            <tx:method name="query*" read-only="true" timeout="10"/>
            
            <!-- 修改方法:读写事务 -->
            <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
            <tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
            
            <!-- 批量操作:需要新事务 -->
            <tx:method name="batch*" propagation="REQUIRES_NEW" timeout="300"/>
            
            <!-- 其他方法:默认事务 -->
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    
    <!-- 配置AOP切面 -->
    <aop:config>
        <aop:pointcut id="txPointcut" expression="execution(* com.example.service.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>
</beans>

2. 多事务管理器配置

<!-- 主数据源事务管理器 -->
<bean id="primaryTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="primaryDataSource"/>
    <qualifier value="primary"/>
</bean>

<!-- 从数据源事务管理器 -->
<bean id="secondaryTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="secondaryDataSource"/>
    <qualifier value="secondary"/>
</bean>

<!-- 主数据源事务通知 -->
<tx:advice id="primaryTxAdvice" transaction-manager="primaryTransactionManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

<!-- 从数据源事务通知 -->
<tx:advice id="secondaryTxAdvice" transaction-manager="secondaryTransactionManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

编程式事务

TransactionTemplate 方式

1. 基本用法

@Service
public class ProgrammaticTransactionService {
    
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    @Autowired
    private AccountDao accountDao;
    
    /**
     * 使用TransactionTemplate进行编程式事务管理
     */
    public void transferMoney(String fromAccount, String toAccount, BigDecimal amount) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    // 检查源账户余额
                    Account from = accountDao.findByAccountNumber(fromAccount);
                    if (from.getBalance().compareTo(amount) < 0) {
                        throw new InsufficientFundsException("余额不足");
                    }
                    
                    // 扣款
                    from.setBalance(from.getBalance().subtract(amount));
                    accountDao.update(from);
                    
                    // 模拟异常情况
                    if (amount.compareTo(new BigDecimal("10000")) > 0) {
                        throw new IllegalArgumentException("转账金额过大");
                    }
                    
                    // 加款
                    Account to = accountDao.findByAccountNumber(toAccount);
                    to.setBalance(to.getBalance().add(amount));
                    accountDao.update(to);
                    
                    // 记录交易日志
                    TransactionLog log = new TransactionLog(fromAccount, toAccount, amount);
                    transactionLogDao.save(log);
                    
                } catch (Exception e) {
                    // 标记回滚
                    status.setRollbackOnly();
                    throw new TransactionException("转账失败", e);
                }
            }
        });
    }
    
    /**
     * 带返回值的事务操作
     */
    public Order createOrder(OrderRequest request) {
        return transactionTemplate.execute(new TransactionCallback<Order>() {
            @Override
            public Order doInTransaction(TransactionStatus status) {
                // 创建订单
                Order order = new Order(request);
                order = orderDao.save(order);
                
                // 减少库存
                for (OrderItem item : order.getItems()) {
                    Product product = productDao.findById(item.getProductId());
                    if (product.getStock() < item.getQuantity()) {
                        status.setRollbackOnly();
                        throw new InsufficientStockException("库存不足");
                    }
                    product.setStock(product.getStock() - item.getQuantity());
                    productDao.update(product);
                }
                
                return order;
            }
        });
    }
}

2. 自定义TransactionTemplate

@Configuration
public class TransactionConfig {
    
    @Bean
    public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
        TransactionTemplate template = new TransactionTemplate(transactionManager);
        
        // 设置事务属性
        template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        template.setTimeout(30);
        template.setReadOnly(false);
        
        return template;
    }
    
    @Bean
    public TransactionTemplate readOnlyTransactionTemplate(PlatformTransactionManager transactionManager) {
        TransactionTemplate template = new TransactionTemplate(transactionManager);
        
        // 只读事务模板
        template.setReadOnly(true);
        template.setTimeout(10);
        
        return template;
    }
}

PlatformTransactionManager 方式

1. 直接使用事务管理器

@Service
public class DirectTransactionService {
    
    @Autowired
    private PlatformTransactionManager transactionManager;
    
    @Autowired
    private UserDao userDao;
    
    public void registerUser(User user) {
        // 定义事务属性
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        def.setTimeout(30);
        
        // 开始事务
        TransactionStatus status = transactionManager.getTransaction(def);
        
        try {
            // 业务逻辑
            validateUser(user);
            userDao.save(user);
            
            // 发送欢迎邮件
            emailService.sendWelcomeEmail(user.getEmail());
            
            // 提交事务
            transactionManager.commit(status);
            
        } catch (Exception e) {
            // 回滚事务
            transactionManager.rollback(status);
            throw new ServiceException("用户注册失败", e);
        }
    }
    
    /**
     * 嵌套事务示例
     */
    public void processOrderWithSavepoint(Order order) {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);
        
        try {
            // 保存订单
            orderDao.save(order);
            
            // 创建保存点
            Object savepoint = status.createSavepoint();
            
            try {
                // 发送通知
                notificationService.sendOrderNotification(order);
                
                // 释放保存点
                status.releaseSavepoint(savepoint);
                
            } catch (Exception e) {
                // 回滚到保存点
                status.rollbackToSavepoint(savepoint);
                logger.error("发送通知失败,回滚到保存点", e);
            }
            
            // 更新库存
            updateInventory(order);
            
            // 提交事务
            transactionManager.commit(status);
            
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw new ServiceException("订单处理失败", e);
        }
    }
}

事务传播机制

传播属性详解

1. REQUIRED(默认)

如果当前存在事务,则加入该事务;如果没有事务,则创建一个新事务。

@Service
public class PropagationRequiredDemo {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
        // 创建新事务
        System.out.println("Method A 开始执行");
        userDao.save(new User("用户A"));
        
        // 调用方法B,加入当前事务
        methodB();
        
        System.out.println("Method A 执行完成");
    }
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        // 加入methodA的事务
        System.out.println("Method B 开始执行");
        userDao.save(new User("用户B"));
        
        // 如果这里抛出异常,整个事务都会回滚
        if (someCondition()) {
            throw new RuntimeException("Method B 执行失败");
        }
        
        System.out.println("Method B 执行完成");
    }
}

2. REQUIRES_NEW

无论当前是否存在事务,都创建一个新事务。

@Service
public class PropagationRequiresNewDemo {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void outerMethod() {
        System.out.println("外部事务开始");
        userDao.save(new User("外部用户"));
        
        try {
            // 调用内部方法,创建新事务
            innerMethod();
        } catch (Exception e) {
            // 内部事务的异常不会影响外部事务
            System.out.println("内部事务失败,但外部事务继续");
        }
        
        System.out.println("外部事务结束");
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void innerMethod() {
        System.out.println("内部事务开始");
        userDao.save(new User("内部用户"));
        
        // 这个异常只会回滚内部事务
        throw new RuntimeException("内部事务失败");
    }
}

3. NESTED

如果当前存在事务,则在嵌套事务内执行;如果没有事务,则创建一个新事务。

@Service
public class PropagationNestedDemo {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void parentMethod() {
        System.out.println("父事务开始");
        userDao.save(new User("父事务用户"));
        
        try {
            // 嵌套事务
            nestedMethod();
        } catch (Exception e) {
            // 嵌套事务失败,可以选择是否回滚父事务
            System.out.println("嵌套事务失败,父事务继续");
        }
        
        System.out.println("父事务结束");
    }
    
    @Transactional(propagation = Propagation.NESTED)
    public void nestedMethod() {
        System.out.println("嵌套事务开始");
        userDao.save(new User("嵌套事务用户"));
        
        // 嵌套事务失败,回滚到保存点
        throw new RuntimeException("嵌套事务失败");
    }
}

4. SUPPORTS

如果当前存在事务,则加入该事务;如果没有事务,则以非事务方式执行。

@Service
public class PropagationSupportsDemo {
    
    @Transactional(propagation = Propagation.SUPPORTS)
    public void supportMethod() {
        // 如果被事务方法调用,则加入事务
        // 如果被非事务方法调用,则以非事务方式执行
        userDao.save(new User("支持事务用户"));
    }
    
    @Transactional
    public void withTransaction() {
        // supportMethod会加入当前事务
        supportMethod();
    }
    
    public void withoutTransaction() {
        // supportMethod以非事务方式执行
        supportMethod();
    }
}

5. NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,则把当前事务挂起。

@Service
public class PropagationNotSupportedDemo {
    
    @Transactional
    public void transactionalMethod() {
        System.out.println("事务方法开始");
        userDao.save(new User("事务用户"));
        
        // 调用非事务方法,当前事务被挂起
        nonTransactionalMethod();
        
        System.out.println("事务方法结束");
    }
    
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void nonTransactionalMethod() {
        System.out.println("非事务方法执行");
        // 这里的操作不在事务中,会立即提交
        userDao.save(new User("非事务用户"));
    }
}

6. MANDATORY

必须在现有事务中执行,如果没有事务则抛出异常。

@Service
public class PropagationMandatoryDemo {
    
    @Transactional(propagation = Propagation.MANDATORY)
    public void mandatoryMethod() {
        // 必须在事务中执行
        userDao.save(new User("强制事务用户"));
    }
    
    @Transactional
    public void callMandatoryMethod() {
        // 正常调用,因为在事务中
        mandatoryMethod();
    }
    
    public void callWithoutTransaction() {
        // 这里会抛出IllegalTransactionStateException
        mandatoryMethod();
    }
}

7. NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。

@Service
public class PropagationNeverDemo {
    
    @Transactional(propagation = Propagation.NEVER)
    public void neverMethod() {
        // 绝不能在事务中执行
        userDao.save(new User("绝不事务用户"));
    }
    
    public void callNeverMethod() {
        // 正常调用,因为没有事务
        neverMethod();
    }
    
    @Transactional
    public void callWithTransaction() {
        // 这里会抛出IllegalTransactionStateException
        neverMethod();
    }
}

事务隔离级别

隔离级别详解

1. READ_UNCOMMITTED(读未提交)

最低隔离级别,允许读取尚未提交的数据变更。

@Service
public class ReadUncommittedDemo {
    
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    public void readUncommittedData() {
        // 可能读取到其他事务未提交的数据(脏读)
        List<Account> accounts = accountDao.findAll();
        
        for (Account account : accounts) {
            System.out.println("账户余额:" + account.getBalance());
            // 这个余额可能是其他事务未提交的临时值
        }
    }
}

2. READ_COMMITTED(读已提交)

允许读取并发事务已经提交的数据。

@Service
public class ReadCommittedDemo {
    
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void readCommittedData() {
        // 第一次读取
        Account account = accountDao.findById(1L);
        BigDecimal balance1 = account.getBalance();
        System.out.println("第一次读取余额:" + balance1);
        
        // 模拟等待,其他事务可能修改并提交数据
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        // 第二次读取
        account = accountDao.findById(1L);
        BigDecimal balance2 = account.getBalance();
        System.out.println("第二次读取余额:" + balance2);
        
        // 可能出现不可重复读
        if (!balance1.equals(balance2)) {
            System.out.println("发生了不可重复读");
        }
    }
}

3. REPEATABLE_READ(可重复读)

对同一字段的多次读取结果都是一致的。

@Service
public class RepeatableReadDemo {
    
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    public void repeatableReadData() {
        // 第一次读取
        Account account = accountDao.findById(1L);
        BigDecimal balance1 = account.getBalance();
        System.out.println("第一次读取余额:" + balance1);
        
        // 模拟长时间处理
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        // 第二次读取
        account = accountDao.findById(1L);
        BigDecimal balance2 = account.getBalance();
        System.out.println("第二次读取余额:" + balance2);
        
        // 在可重复读隔离级别下,两次读取结果应该相同
        assert balance1.equals(balance2) : "可重复读保证失败";
        
        // 但是可能出现幻读
        List<Account> accounts1 = accountDao.findByBalanceGreaterThan(new BigDecimal("1000"));
        System.out.println("第一次查询账户数量:" + accounts1.size());
        
        // 再次查询
        List<Account> accounts2 = accountDao.findByBalanceGreaterThan(new BigDecimal("1000"));
        System.out.println("第二次查询账户数量:" + accounts2.size());
    }
}

4. SERIALIZABLE(可串行化)

最高隔离级别,完全服从ACID原则。

@Service
public class SerializableDemo {
    
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void serializableTransaction() {
        // 在可串行化隔离级别下,不会出现任何并发问题
        List<Account> accounts = accountDao.findAll();
        
        for (Account account : accounts) {
            // 对每个账户进行复杂的计算
            BigDecimal interest = calculateInterest(account);
            account.setBalance(account.getBalance().add(interest));
            accountDao.update(account);
        }
        
        // 在此事务执行期间,其他事务无法读取或修改账户数据
        System.out.println("所有账户利息计算完成");
    }
    
    private BigDecimal calculateInterest(Account account) {
        // 复杂的利息计算逻辑
        return account.getBalance().multiply(new BigDecimal("0.05"));
    }
}

事务回滚规则

默认回滚规则

@Service
public class RollbackRuleDemo {
    
    /**
     * 默认回滚规则:RuntimeException和Error会回滚
     */
    @Transactional
    public void defaultRollbackRule() {
        userDao.save(new User("测试用户"));
        
        // 这会导致事务回滚
        throw new RuntimeException("运行时异常");
    }
    
    /**
     * 检查型异常不会回滚
     */
    @Transactional
    public void checkedExceptionNoRollback() throws Exception {
        userDao.save(new User("测试用户"));
        
        // 这不会导致事务回滚
        throw new Exception("检查型异常");
    }
}

自定义回滚规则

@Service
public class CustomRollbackRuleDemo {
    
    /**
     * 指定回滚异常类型
     */
    @Transactional(rollbackFor = {Exception.class, CustomException.class})
    public void customRollbackFor() throws Exception {
        userDao.save(new User("测试用户"));
        
        // 即使是检查型异常,也会回滚
        throw new Exception("自定义回滚异常");
    }
    
    /**
     * 指定不回滚的异常类型
     */
    @Transactional(noRollbackFor = {IllegalArgumentException.class})
    public void customNoRollbackFor() {
        userDao.save(new User("测试用户"));
        
        // 即使是RuntimeException,也不会回滚
        throw new IllegalArgumentException("不回滚异常");
    }
    
    /**
     * 按异常类名指定回滚规则
     */
    @Transactional(
        rollbackForClassName = {"java.lang.Exception", "com.example.CustomException"},
        noRollbackForClassName = {"java.lang.IllegalArgumentException"}
    )
    public void rollbackByClassName() throws Exception {
        userDao.save(new User("测试用户"));
        
        // 业务逻辑
        if (someCondition()) {
            throw new Exception("按类名回滚");
        }
    }
    
    /**
     * 程序化设置回滚
     */
    @Transactional
    public void programmaticRollback() {
        try {
            userDao.save(new User("测试用户"));
            
            // 业务逻辑
            if (someBusinessCondition()) {
                // 手动标记回滚
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return;
            }
            
        } catch (Exception e) {
            // 处理异常但不抛出,事务不会自动回滚
            logger.error("业务处理失败", e);
            
            // 手动标记回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }
}

分布式事务

两阶段提交(2PC)

1. JTA事务管理器配置

@Configuration
@EnableTransactionManagement
public class JtaTransactionConfig {
    
    @Bean
    public JtaTransactionManager transactionManager() {
        JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
        jtaTransactionManager.setUserTransaction(userTransaction());
        jtaTransactionManager.setTransactionManager(atomikosTransactionManager());
        return jtaTransactionManager;
    }
    
    @Bean
    public UserTransaction userTransaction() {
        UserTransactionImp userTransactionImp = new UserTransactionImp();
        userTransactionImp.setTransactionTimeout(300);
        return userTransactionImp;
    }
    
    @Bean
    public TransactionManager atomikosTransactionManager() {
        UserTransactionManager userTransactionManager = new UserTransactionManager();
        userTransactionManager.setForceShutdown(false);
        return userTransactionManager;
    }
}

2. 多数据源配置

@Configuration
public class MultiDataSourceConfig {
    
    @Bean
    @Primary
    public DataSource primaryDataSource() {
        AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
        dataSource.setUniqueResourceName("primary");
        dataSource.setXaDataSourceClassName("com.mysql.cj.jdbc.MysqlXADataSource");
        
        Properties properties = new Properties();
        properties.setProperty("url", "jdbc:mysql://localhost:3306/primary_db");
        properties.setProperty("user", "root");
        properties.setProperty("password", "password");
        dataSource.setXaProperties(properties);
        
        return dataSource;
    }
    
    @Bean
    public DataSource secondaryDataSource() {
        AtomikosDataSourceBean dataSource = new AtomikosDataSourceBean();
        dataSource.setUniqueResourceName("secondary");
        dataSource.setXaDataSourceClassName("com.mysql.cj.jdbc.MysqlXADataSource");
        
        Properties properties = new Properties();
        properties.setProperty("url", "jdbc:mysql://localhost:3306/secondary_db");
        properties.setProperty("user", "root");
        properties.setProperty("password", "password");
        dataSource.setXaProperties(properties);
        
        return dataSource;
    }
}

3. 分布式事务服务

@Service
public class DistributedTransactionService {
    
    @Autowired
    @Qualifier("primaryDataSource")
    private DataSource primaryDataSource;
    
    @Autowired
    @Qualifier("secondaryDataSource")
    private DataSource secondaryDataSource;
    
    @Transactional
    public void distributedTransaction() {
        // 在主数据库中操作
        try (Connection primaryConn = primaryDataSource.getConnection()) {
            String sql = "INSERT INTO orders (order_id, amount) VALUES (?, ?)";
            PreparedStatement ps = primaryConn.prepareStatement(sql);
            ps.setString(1, "ORDER-001");
            ps.setBigDecimal(2, new BigDecimal("100.00"));
            ps.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("主数据库操作失败", e);
        }
        
        // 在从数据库中操作
        try (Connection secondaryConn = secondaryDataSource.getConnection()) {
            String sql = "INSERT INTO inventory (product_id, quantity) VALUES (?, ?)";
            PreparedStatement ps = secondaryConn.prepareStatement(sql);
            ps.setString(1, "PRODUCT-001");
            ps.setInt(2, -1);
            ps.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("从数据库操作失败", e);
        }
        
        // 如果任何一个操作失败,整个分布式事务都会回滚
    }
}

Seata分布式事务

1. Seata配置

@Configuration
public class SeataConfig {
    
    @Bean
    public GlobalTransactionScanner globalTransactionScanner() {
        return new GlobalTransactionScanner("my-service-group", "my-tx-group");
    }
}

2. 使用Seata管理分布式事务

@Service
public class SeataTransactionService {
    
    @Autowired
    private OrderService orderService;
    
    @Autowired
    private InventoryService inventoryService;
    
    @Autowired
    private PaymentService paymentService;
    
    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    public void createOrder(OrderRequest request) {
        // 创建订单
        Order order = orderService.createOrder(request);
        
        // 扣减库存
        inventoryService.reduceStock(request.getProductId(), request.getQuantity());
        
        // 扣减余额
        paymentService.deductBalance(request.getUserId(), request.getAmount());
        
        // 如果任何一个服务调用失败,全局事务会回滚
    }
}

性能优化

1. 事务范围优化

@Service
public class TransactionOptimizationService {
    
    /**
     * 不好的做法:事务范围过大
     */
    @Transactional
    public void badTransactionScope() {
        // 耗时的非数据库操作
        String result = callRemoteService(); // 网络调用
        
        // 复杂的业务逻辑计算
        BigDecimal calculatedValue = performComplexCalculation(result);
        
        // 数据库操作
        userDao.updateBalance(userId, calculatedValue);
        
        // 发送邮件
        emailService.sendNotification(userId, calculatedValue);
    }
    
    /**
     * 好的做法:缩小事务范围
     */
    public void goodTransactionScope() {
        // 先进行非数据库操作
        String result = callRemoteService();
        BigDecimal calculatedValue = performComplexCalculation(result);
        
        // 只在数据库操作时开启事务
        updateBalanceInTransaction(userId, calculatedValue);
        
        // 事务外发送邮件
        emailService.sendNotification(userId, calculatedValue);
    }
    
    @Transactional
    private void updateBalanceInTransaction(Long userId, BigDecimal amount) {
        userDao.updateBalance(userId, amount);
    }
}

2. 只读事务优化

@Service
public class ReadOnlyTransactionService {
    
    /**
     * 只读事务可以提高性能
     */
    @Transactional(readOnly = true)
    public List<User> getUsersByCondition(UserQueryCondition condition) {
        // 只读事务可以:
        // 1. 省略事务日志记录
        // 2. 优化数据库锁机制
        // 3. 使用只读数据源
        return userDao.findByCondition(condition);
    }
    
    /**
     * 批量只读操作
     */
    @Transactional(readOnly = true, timeout = 30)
    public UserStatistics calculateUserStatistics() {
        List<User> allUsers = userDao.findAll();
        List<Order> allOrders = orderDao.findAll();
        
        return new UserStatistics(allUsers, allOrders);
    }
}

3. 事务超时设置

@Service
public class TransactionTimeoutService {
    
    /**
     * 设置事务超时时间
     */
    @Transactional(timeout = 30) // 30秒超时
    public void batchOperation() {
        // 批量操作
        List<User> users = userDao.findInactiveUsers();
        
        for (User user : users) {
            // 处理每个用户
            processUser(user);
        }
    }
    
    /**
     * 分批处理大量数据
     */
    @Transactional(timeout = 10)
    public void batchProcessInChunks() {
        int batchSize = 100;
        int offset = 0;
        
        List<User> users;
        do {
            users = userDao.findInactiveUsers(offset, batchSize);
            
            for (User user : users) {
                processUser(user);
            }
            
            offset += batchSize;
        } while (users.size() == batchSize);
    }
}

4. 异步事务处理

@Service
public class AsyncTransactionService {
    
    @Autowired
    private TaskExecutor taskExecutor;
    
    public void processOrderAsync(Order order) {
        // 主要的订单处理(同步)
        processOrderSync(order);
        
        // 异步处理次要任务
        taskExecutor.execute(() -> {
            processOrderNotificationAsync(order);
        });
    }
    
    @Transactional
    private void processOrderSync(Order order) {
        // 核心业务逻辑
        orderDao.save(order);
        inventoryService.reduceStock(order);
    }
    
    @Async
    @Transactional
    public void processOrderNotificationAsync(Order order) {
        // 异步事务处理
        notificationService.sendOrderNotification(order);
        auditService.logOrderCreated(order);
    }
}

实战案例

电商订单处理

@Service
@Transactional
public class OrderProcessingService {
    
    @Autowired
    private OrderDao orderDao;
    
    @Autowired
    private InventoryService inventoryService;
    
    @Autowired
    private PaymentService paymentService;
    
    @Autowired
    private CouponService couponService;
    
    @Autowired
    private PointService pointService;
    
    /**
     * 处理订单创建
     */
    @Transactional(
        propagation = Propagation.REQUIRED,
        isolation = Isolation.READ_COMMITTED,
        timeout = 30,
        rollbackFor = Exception.class
    )
    public OrderResult createOrder(CreateOrderRequest request) {
        try {
            // 1. 验证请求参数
            validateOrderRequest(request);
            
            // 2. 检查库存
            inventoryService.checkStock(request.getItems());
            
            // 3. 验证优惠券
            CouponValidationResult couponResult = null;
            if (request.getCouponId() != null) {
                couponResult = couponService.validateCoupon(request.getCouponId(), request.getUserId());
            }
            
            // 4. 计算订单金额
            OrderAmount amount = calculateOrderAmount(request, couponResult);
            
            // 5. 创建订单
            Order order = createOrderEntity(request, amount);
            order = orderDao.save(order);
            
            // 6. 扣减库存
            inventoryService.reduceStock(request.getItems());
            
            // 7. 处理支付
            PaymentResult paymentResult = paymentService.processPayment(
                request.getUserId(), amount.getPayableAmount());
            
            // 8. 使用优惠券
            if (couponResult != null && couponResult.isValid()) {
                couponService.useCoupon(request.getCouponId(), request.getUserId());
            }
            
            // 9. 增加积分
            pointService.addPoints(request.getUserId(), 
                amount.getPayableAmount().multiply(new BigDecimal("0.01")));
            
            // 10. 更新订单状态
            order.setStatus(OrderStatus.PAID);
            order.setPaymentResult(paymentResult);
            orderDao.update(order);
            
            // 11. 异步处理(事务外)
            processOrderAsync(order);
            
            return new OrderResult(order, paymentResult);
            
        } catch (InsufficientStockException e) {
            throw new OrderProcessingException("库存不足", e);
        } catch (PaymentException e) {
            throw new OrderProcessingException("支付失败", e);
        } catch (Exception e) {
            throw new OrderProcessingException("订单处理失败", e);
        }
    }
    
    /**
     * 处理订单取消
     */
    @Transactional(
        propagation = Propagation.REQUIRED,
        rollbackFor = Exception.class
    )
    public void cancelOrder(Long orderId, String reason) {
        Order order = orderDao.findById(orderId);
        
        if (order == null) {
            throw new OrderNotFoundException("订单不存在");
        }
        
        if (!order.canCancel()) {
            throw new OrderStatusException("订单状态不允许取消");
        }
        
        // 恢复库存
        inventoryService.restoreStock(order.getItems());
        
        // 退款
        if (order.getStatus() == OrderStatus.PAID) {
            paymentService.refund(order.getPaymentResult().getPaymentId());
        }
        
        // 恢复优惠券
        if (order.getCouponId() != null) {
            couponService.restoreCoupon(order.getCouponId(), order.getUserId());
        }
        
        // 扣减积分
        pointService.deductPoints(order.getUserId(), order.getPointsEarned());
        
        // 更新订单状态
        order.setStatus(OrderStatus.CANCELLED);
        order.setCancelReason(reason);
        order.setCancelTime(new Date());
        orderDao.update(order);
    }
    
    /**
     * 异步处理订单相关任务
     */
    @Async
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void processOrderAsync(Order order) {
        try {
            // 发送订单确认邮件
            emailService.sendOrderConfirmation(order);
            
            // 推送消息
            pushService.pushOrderCreated(order);
            
            // 记录操作日志
            auditService.logOrderCreated(order);
            
            // 更新用户统计
            userStatisticsService.updateOrderStatistics(order.getUserId());
            
        } catch (Exception e) {
            logger.error("异步处理订单失败", e);
            // 异步任务失败不影响主流程
        }
    }
}

银行转账系统

@Service
public class BankTransferService {
    
    @Autowired
    private AccountDao accountDao;
    
    @Autowired
    private TransactionLogDao transactionLogDao;
    
    @Autowired
    private RiskControlService riskControlService;
    
    /**
     * 转账操作
     */
    @Transactional(
        propagation = Propagation.REQUIRED,
        isolation = Isolation.READ_COMMITTED,
        timeout = 30,
        rollbackFor = Exception.class
    )
    public TransferResult transfer(TransferRequest request) {
        // 1. 参数验证
        validateTransferRequest(request);
        
        // 2. 风险控制检查
        riskControlService.checkTransferRisk(request);
        
        // 3. 加载账户(加锁)
        Account fromAccount = accountDao.findByIdForUpdate(request.getFromAccountId());
        Account toAccount = accountDao.findByIdForUpdate(request.getToAccountId());
        
        // 4. 业务规则检查
        validateTransferBusiness(fromAccount, toAccount, request.getAmount());
        
        // 5. 执行转账
        fromAccount.debit(request.getAmount());
        toAccount.credit(request.getAmount());
        
        // 6. 更新账户
        accountDao.update(fromAccount);
        accountDao.update(toAccount);
        
        // 7. 记录交易日志
        TransactionLog log = new TransactionLog(
            request.getFromAccountId(),
            request.getToAccountId(),
            request.getAmount(),
            TransactionType.TRANSFER,
            request.getDescription()
        );
        transactionLogDao.save(log);
        
        return new TransferResult(log.getId(), TransferStatus.SUCCESS);
    }
    
    /**
     * 批量转账
     */
    @Transactional(
        propagation = Propagation.REQUIRED,
        timeout = 300,
        rollbackFor = Exception.class
    )
    public BatchTransferResult batchTransfer(List<TransferRequest> requests) {
        List<TransferResult> results = new ArrayList<>();
        BigDecimal totalAmount = BigDecimal.ZERO;
        
        for (TransferRequest request : requests) {
            try {
                TransferResult result = processSingleTransfer(request);
                results.add(result);
                totalAmount = totalAmount.add(request.getAmount());
            } catch (Exception e) {
                // 单笔转账失败,整批回滚
                throw new BatchTransferException("批量转账失败", e);
            }
        }
        
        return new BatchTransferResult(results, totalAmount);
    }
    
    private TransferResult processSingleTransfer(TransferRequest request) {
        // 单笔转账逻辑(不使用@Transactional,继承外部事务)
        return transfer(request);
    }
}

常见问题

问题1:事务不生效

❓ 现象: 添加了@Transactional注解但事务不生效

常见原因:

  1. 方法访问权限不是public
  2. 类没有被Spring管理
  3. 自调用问题
  4. 异常被捕获没有抛出

解决方案:

// ❌ 错误示例
@Service
public class UserService {
    
    // 问题1:方法不是public
    @Transactional
    private void saveUser(User user) {
        userDao.save(user);
    }
    
    // 问题2:自调用
    @Transactional
    public void method1() {
        // 直接调用不会走代理
        method2();
    }
    
    @Transactional
    public void method2() {
        userDao.save(new User());
    }
    
    // 问题3:异常被捕获
    @Transactional
    public void method3() {
        try {
            userDao.save(new User());
            int i = 1 / 0; // 异常
        } catch (Exception e) {
            // 异常被捕获,事务不会回滚
        }
    }
}

// ✅ 正确示例
@Service
public class UserService {
    
    @Autowired
    private UserService self; // 注入自己的代理
    
    @Transactional
    public void saveUser(User user) {
        userDao.save(user);
    }
    
    @Transactional
    public void method1() {
        // 通过代理调用
        self.method2();
    }
    
    @Transactional
    public void method2() {
        userDao.save(new User());
    }
    
    @Transactional
    public void method3() {
        try {
            userDao.save(new User());
            int i = 1 / 0;
        } catch (Exception e) {
            // 重新抛出异常
            throw new ServiceException("保存用户失败", e);
        }
    }
}

问题2:事务传播行为理解错误

❓ 现象: 事务传播行为不符合预期

解决方案:

@Service
public class TransactionPropagationService {
    
    @Transactional(propagation = Propagation.REQUIRED)
    public void outerMethod() {
        userDao.save(new User("外部用户"));
        
        try {
            // REQUIRES_NEW会创建新事务
            innerMethodRequiresNew();
        } catch (Exception e) {
            // 内部事务失败不会影响外部事务
            System.out.println("内部事务失败,外部事务继续");
        }
    }
    
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void innerMethodRequiresNew() {
        userDao.save(new User("内部用户"));
        throw new RuntimeException("内部事务失败");
    }
}

问题3:数据库死锁

❓ 现象: 在高并发情况下出现数据库死锁

解决方案:

@Service
public class DeadlockAvoidanceService {
    
    @Transactional
    public void transfer(Long fromAccountId, Long toAccountId, BigDecimal amount) {
        // 按ID排序获取锁,避免死锁
        Long firstId = fromAccountId < toAccountId ? fromAccountId : toAccountId;
        Long secondId = fromAccountId < toAccountId ? toAccountId : fromAccountId;
        
        Account firstAccount = accountDao.findByIdForUpdate(firstId);
        Account secondAccount = accountDao.findByIdForUpdate(secondId);
        
        // 确定哪个是转出账户,哪个是转入账户
        Account fromAccount = fromAccountId.equals(firstId) ? firstAccount : secondAccount;
        Account toAccount = toAccountId.equals(firstId) ? firstAccount : secondAccount;
        
        // 执行转账
        fromAccount.debit(amount);
        toAccount.credit(amount);
        
        accountDao.update(fromAccount);
        accountDao.update(toAccount);
    }
}

问题4:长事务导致性能问题

❓ 现象: 长时间运行的事务导致系统性能下降

解决方案:

@Service
public class LongTransactionOptimizationService {
    
    // ❌ 错误:长事务
    @Transactional
    public void processLargeDataBad() {
        List<User> users = userDao.findAll(); // 可能很多数据
        
        for (User user : users) {
            // 复杂的业务逻辑
            processUser(user);
            userDao.update(user);
        }
    }
    
    // ✅ 正确:分批处理
    public void processLargeDataGood() {
        int batchSize = 100;
        int offset = 0;
        
        List<User> users;
        do {
            users = processBatch(offset, batchSize);
            offset += batchSize;
        } while (users.size() == batchSize);
    }
    
    @Transactional
    private List<User> processBatch(int offset, int batchSize) {
        List<User> users = userDao.findUsers(offset, batchSize);
        
        for (User user : users) {
            processUser(user);
            userDao.update(user);
        }
        
        return users;
    }
}

相关文章

Spring基础系列

Spring MVC系列

MyBatis集成

SpringBoot现代化开发

数据库相关

  • MySQL性能优化 - 数据库调优
  • Redis缓存策略 - 缓存应用

分布式系统

  • 分布式事务解决方案 - 分布式一致性
  • 消息队列应用 - 异步处理

总结

Spring事务管理是企业级应用开发的核心技术,通过统一的事务抽象和灵活的配置方式,大大简化了事务编程的复杂性。

🎯 核心价值

  • 统一抽象:屏蔽底层事务实现差异,提供一致的编程模型
  • 声明式管理:通过注解或配置实现非侵入式事务管理
  • 灵活配置:支持多种传播机制和隔离级别
  • 异常处理:智能的事务回滚和异常处理机制

🛠️ 技术要点

  1. 事务基础:ACID属性、并发问题、隔离级别
  2. Spring架构:事务管理器、事务定义、事务状态
  3. 声明式事务:注解配置、XML配置、传播机制
  4. 编程式事务:TransactionTemplate、PlatformTransactionManager
  5. 分布式事务:JTA、Seata、两阶段提交

🚀 最佳实践

  1. 合理选择事务范围:避免长事务,缩小事务边界
  2. 正确使用传播属性:根据业务需求选择合适的传播机制
  3. 优化事务性能:使用只读事务、设置合理超时时间
  4. 处理异常回滚:明确回滚规则,正确处理异常
  5. 避免常见陷阱:自调用、访问权限、异常捕获