Spring 事务入门

1. 事务

事务(Transaction)是在数据库管理系统中执行的一个操作序列,这些操作要么完全执行,要么完全不执行。事务确保数据的一致性和完整性,是数据库应用程序中非常重要的部分。

想象一下你去书店买书。你决定买两本书,交给收银员,然后用银行卡支付。如果支付成功,你就可以拿走书。如果支付失败,收银员会把书拿回来,不会扣除你的钱。这就是一个事务的例子。

事务的四个主要属性 (ACID):

  1. 原子性 (Atomicity): 事务中的所有操作要么全部完成,要么全部不完成。
  2. 一致性 (Consistency): 事务执行前后,数据库从一个一致性状态转换到另一个一致性状态。
  3. 隔离性 (Isolation): 并发事务相互隔离,事务之间不会互相影响。
  4. 持久性 (Durability): 事务完成后,对数据的修改是永久性的,即使系统发生故障也不会丢失。

2. Spring 事务管理

Spring 提供了强大的事务管理功能,可以帮助开发者简化事务处理,提高应用程序的可靠性和数据的一致性。

Spring 事务管理的优点:

  • 统一的编程模型: 不论是 JDBC、Hibernate 还是 JPA,Spring 都提供了统一的事务管理接口。
  • 声明式事务管理: 通过注解或 XML 配置,轻松实现事务管理,而无需大量的代码。
  • 集成性: Spring 事务管理与其他 Spring 组件无缝集成,如 Spring AOP、Spring Data 等。

3. Spring 事务管理的方式

Spring 提供了两种主要的事务管理方式:

  1. 编程式事务管理: 通过编写代码显式地控制事务边界。
  2. 声明式事务管理: 使用注解或 XML 配置来声明事务边界,无需编写大量的事务控制代码。

4. 示例

假设我们有一个银行账户转账的操作,需要确保从一个账户扣款并向另一个账户入款这两个操作要么都成功,要么都不执行,这时就需要使用事务来保证数据的一致性。

4.1 编程式事务管理示例
public void transferMoney(Long fromAccountId, Long toAccountId, Double amount) {
    TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());

    try {
        // 扣款
        accountRepository.debit(fromAccountId, amount);
        // 入款
        accountRepository.credit(toAccountId, amount);
        // 提交事务
        transactionManager.commit(status);
    } catch (Exception e) {
        // 回滚事务
        transactionManager.rollback(status);
        throw e;
    }
}

4.2 声明式事务管理示例
@Transactional
public void transferMoney(Long fromAccountId, Long toAccountId, Double amount) {
    // 扣款
    accountRepository.debit(fromAccountId, amount);
    // 入款
    accountRepository.credit(toAccountId, amount);
}

由于声明式事务比较方便,所以应用的十分广泛,下面主要介绍声明式事务管理(注解形式)。

5. 声明式事务管理

  1. 概述:声明式事务管理是通过配置或注解来声明事务边界,而不需要在代码中显式地管理事务。这样可以使代码更加简洁和易于维护。Spring 提供了基于注解和 XML 配置的两种声明式事务管理方式。

  2. Spring 中最常用的声明式事务管理方式是使用 @Transactional 注解。你可以在类或方法上使用此注解来声明事务。

  3. 基本用法:

@Service
public class AccountService {
    
    @Autowired
    private AccountRepository accountRepository;

    @Transactional
    public void transferMoney(Long fromAccountId, Long toAccountId, Double amount) {
        // 扣款
        accountRepository.debit(fromAccountId, amount);
        // 入款
        accountRepository.credit(toAccountId, amount);
    }
}

  1. @Transactional@Transactional 注解可以配置多个属性来控制事务行为,包括传播行为、隔离级别、超时设置、只读属性等。以下是常用的属性:

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

    • isolation:指定事务的隔离级别,默认值为 Isolation.DEFAULT

    • timeout:指定事务的超时时间(以秒为单位)。

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

    • rollbackFor:指定哪些异常会导致事务回滚。

    • noRollbackFor:指定哪些异常不会导致事务回滚。

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, timeout = 30, rollbackFor = Exception.class)
public void transferMoney(Long fromAccountId, Long toAccountId, Double amount) {
    // 扣款
    accountRepository.debit(fromAccountId, amount);
    // 入款
    accountRepository.credit(toAccountId, amount);
}

解释:

  • Propagation.REQUIRED:这是事务传播行为的配置,表示当前方法必须在一个事务中运行。如果当前存在一个事务,则加入该事务;如果当前没有事务,则创建一个新的事务。

  • Isolation.READ_COMMITTED:这是事务的隔离级别,表示只能读取已经提交的数据,防止脏读(dirty read)。

  • timeout = 30:事务超时时间设置为30秒。如果事务在30秒内没有完成,则会回滚。

  • rollbackFor = Exception.class:指定哪些异常会导致事务回滚。在这里,任何抛出 Exception 类的异常都会导致事务回滚。

  1. 选择适当的事务隔离级别取决于具体的业务需求和性能考虑。在大多数情况下,READ_COMMITTED 是一个较好的选择,因为它在防止脏读的同时提供了较好的性能。而在一些对数据一致性要求较高的场景下,可以选择 REPEATABLE_READSERIALIZABLE

  2. 通过事务管理,Spring能够确保一组操作要么全部成功,要么全部失败,保证数据的一致性和完整性。这在实际开发中非常重要,特别是在金融、电商等关键业务场景中。

  • 19
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值