16:事务-Java Spring

3 阅读4分钟

16.1 Spring事务管理原理

Spring事务管理基于AOP(面向切面编程)实现,通过拦截方法调用,对业务逻辑进行增强,确保事务的正确开启、提交或回滚。其核心组件包括:

  1. PlatformTransactionManager:事务管理器接口,定义了管理和控制事务的基本操作。具体实现如DataSourceTransactionManager(针对JDBC)、HibernateTransactionManager(针对Hibernate)等。

  2. TransactionDefinition:事务定义接口,描述事务的属性,如隔离级别、传播行为、超时时间、是否只读等。

  3. TransactionStatus:事务状态接口,用于查询和控制事务的状态。

16.2 Spring事务配置与代码示例

Spring事务可以通过XML配置、注解驱动等方式进行配置。以下为注解驱动的示例:

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional(rollbackFor = Exception.class)
    public void createUser(String name, String email) {
        User user = new User(name, email);
        userRepository.save(user);

        // 模拟抛出异常,触发事务回滚
        if ("error@example.com".equals(email)) {
            throw new IllegalArgumentException("Invalid email");
        }
    }
}

在上述代码中,@Transactional注解标记了createUser方法为一个事务方法。当该方法内发生未被捕获的异常时,Spring会自动回滚事务,保证数据的一致性。

16.3 事务策略的区别

隔离级别:SQL标准定义了四种隔离级别(读未提交、读已提交、可重复读、串行化),分别对应不同的并发问题(脏读、不可重复读、幻读)。Spring允许开发者根据业务需求调整隔离级别。

  • DEFAULT:由数据库决定。

  • READ_UNCOMMITTED:最低隔离级别,可能发生脏读、不可重复读、幻读。

  • READ_COMMITTED:避免脏读,但可能出现不可重复读、幻读。

  • REPEATABLE_READ:避免脏读、不可重复读,但可能出现幻读。

  • SERIALIZABLE:最高隔离级别,完全避免并发问题,但可能导致性能下降。

@Service
public class TransactionalService {

    // READ_COMMITTED:避免脏读,但可能出现不可重复读、幻读。
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void readCommittedTransaction() {
        // 执行业务逻辑...
    }

    // SERIALIZABLE:最高隔离级别,完全避免并发问题,但可能导致性能下降。
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public void serializableTransaction() {
        // 执行业务逻辑...
    }
}

传播行为:定义了当前方法事务如何与已有事务(如果存在)交互。常见的传播行为有:

  • REQUIRED:若当前存在事务,则加入该事务;否则创建新事务。
  • REQUIRES_NEW:无论当前是否存在事务,均创建新事务。原事务挂起。
  • SUPPORTS:若当前存在事务,则加入该事务;否则以非事务方式执行。
  • NOT_SUPPORTED:以非事务方式执行,若当前存在事务,则挂起。
@Service
public class TransactionalService {

    @Autowired
    private AnotherService anotherService;

    // REQUIRED:如果当前存在事务,则加入该事务;否则创建新事务。
    @Transactional(propagation = Propagation.REQUIRED)
    public void requiredTransaction() {
        // 执行业务逻辑...
        anotherService.someMethod();
    }

    // REQUIRES_NEW:总是新建事务,当前事务(若有)挂起。
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void requiresNewTransaction() {
        // 执行业务逻辑...
    }

    // NEVER:不能在事务环境下执行,否则抛出异常。
    @Transactional(propagation = Propagation.NEVER)
    public void neverTransaction() {
        // 执行业务逻辑...
    }
}

超时设置:指定事务可以持续的最长时间,防止事务长时间阻塞资源。

只读标志:声明事务为只读,数据库可能据此优化查询性能,某些数据库在只读事务中不允许执行更新操作。

@Service
public class TransactionalService {

    @Transactional(readOnly = true)
    public void readOnlyTransaction() {
        // 执行只读查询操作...
    }
}

16.4 Spring事务应用场景总结

  1. 数据密集型业务:如银行转账、订单处理、库存管理等,涉及多个数据库操作,必须保证事务的ACID特性以维护数据一致性。

  2. 分布式事务:Spring支持与分布式事务解决方案(如两阶段提交、Saga模式、Seata等)集成,适用于微服务架构中的跨服务数据一致性问题。

  3. 批量操作:对于大量数据的插入、更新、删除等操作,使用事务可以确保操作的原子性,避免部分成功导致的数据不一致。

  4. 幂等性保障:对于需要保证幂等性的接口(如支付、退款等),利用事务可以确保在并发请求下,多次相同的请求对系统状态的影响与一次请求相同。

总结,Spring事务管理为开发者提供了便捷、强大的事务控制工具。理解其原理、掌握配置与使用方法,并依据业务场景选择合适的事务策略,是构建健壮、可靠的企业级应用的关键。