文章目录
-
- 为什么需要事务?
- [1. 声明式事务](#1. 声明式事务)
- [2. 编程式事务管理](#2. 编程式事务管理)
- [3. 事务的实现原理](#3. 事务的实现原理)
-
- [3.1 事务管理器(Transaction Manager):](#3.1 事务管理器(Transaction Manager):)
- [3.2 事务管理的抽象层:](#3.2 事务管理的抽象层:)
- [3.3 事务传播行为(Propagation Behavior):](#3.3 事务传播行为(Propagation Behavior):)
- [3.4 事务隔离级别(Isolation Level):](#3.4 事务隔离级别(Isolation Level):)
- [3.5 事务的切点(Pointcut)和通知(Advice):](#3.5 事务的切点(Pointcut)和通知(Advice):)
- [3.6 异常处理和事务回滚:](#3.6 异常处理和事务回滚:)
为什么需要事务?
事务 (Transaction)是数据库管理系统(DBMS)中的一个重要概念,它确保数据库操作的一致性 、完整性 和持久性。在软件开发中,特别是涉及到多个数据库操作或者复杂的数据更新过程时,使用事务能够有效地保证数据操作的正确性和可靠性。以下是几个需要事务的主要原因:
保证数据的一致性:
当多个操作必须要一起执行,要么全部成功,要么全部失败时,就需要使用事务。例如,转账操作中,从一个账户扣除金额和向另一个账户增加金额必须作为一个原子操作,否则可能导致数据不一致。
确保数据的完整性:
数据库设计中通常会定义各种约束条件(如主键、唯一性约束、外键约束等),事务能够保证在进行数据操作时,这些约束条件不会被破坏。如果事务执行失败,数据库会自动回滚到事务开始之前的状态,确保数据完整性。
支持并发控制:
当多个用户或者应用程序同时对数据库进行读写操作时,可能会引发并发问题,如脏读(dirty
read)、不可重复读(non-repeatable read)和幻读(phantom
read)。事务使用隔离级别(如读未提交、读已提交、可重复读、串行化)来解决这些并发问题,确保数据的一致性和隔离性。
提供数据持久性:
当事务成功提交后,数据库会将事务所做的所有更改永久保存到磁盘,即使发生系统崩溃或者断电等异常情况,数据也不会丢失。事务的持久性保证了数据的安全性和可靠性。
简化错误处理:
使用事务可以减少因为程序错误、系统故障或者其他异常情况而导致的数据不一致问题。如果事务执行过程中发生异常,数据库会回滚事务,放弃所有未提交的操作,保证系统处于一致的状态。
事务管理是软件开发中非常重要的概念之一,它确保了在复杂的数据操作过程中,数据的一致性和完整性得到有效地维护。在 Spring 框架中,事务管理是通过 Spring 的事务抽象层来实现的,它提供了声明式事务管理 和编程式事务管理两种主要方式。
1. 声明式事务
声明式事务管理是通过配置的方式来实现事务的控制,主要依赖于 AOP 和事务管理器来实现。在 Spring 中,使用 @Transactional 注解来标注需要事务管理的方法或类,Spring 容器会自动为这些方法创建事务代理,以确保方法在执行时事务行为得到正确应用。
java
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Transactional
public void saveUser(User user) {
// 保存用户操作
userRepository.save(user);
}
@Transactional(readOnly = true)
public User findUserById(Long userId) {
// 查询用户操作
return userRepository.findById(userId).orElse(null);
}
}
在上述示例中,@Transactional 注解被用来标注 saveUser 和 findUserById 方法,指示这些方法应该在事务控制下执行。在 saveUser 方法中,默认的事务传播行为和隔离级别会被应用,确保在方法执行时会开启事务并在方法结束时提交或回滚事务。
@Transactional 的常用属性:
- readOnly:指定事务是否为只读事务,默认为 false。
- propagation:指定事务的传播行为,
- 例如 Propagation.REQUIRED 表示如果当前没有事务,就创建一个新的事务
- Propagation.REQUIRES_NEW 表示每次都会创建一个新的事务。
- isolation:指定事务的隔离级别,例如 Isolation.DEFAULT、Isolation.READ_COMMITTED 等。
- timeout:指定事务的超时时间,单位为秒。
- rollbackFor / noRollbackFor:指定哪些异常需要回滚事务或者不回滚事务。
2. 编程式事务管理
编程式事务管理是通过编写代码显式地控制事务的开始、提交和回滚,虽然它更加灵活,但通常比较繁琐并且与业务逻辑混合在一起,不利于代码的维护和扩展,因此在 Spring 中不推荐使用。
java
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import javax.annotation.Resource;
@Service
public class UserService {
@Resource
private PlatformTransactionManager transactionManager;
public void saveUser(User user) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 执行保存用户操作
userRepository.save(user);
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
throw e;
}
}
}
在上述编程式事务管理的示例中,通过 PlatformTransactionManager 和 TransactionStatus 对象来手动管理事务的开始、提交和回滚。这种方式需要开发者显式地编写事务管理的逻辑,包括异常处理和事务状态的管理,相比声明式事务管理更为复杂。
3. 事务的实现原理
在 Spring 框架中,事务的实现原理主要基于 Spring 的事务管理抽象和底层的事务管理器 (Transaction Manager)来实现。Spring 提供了声明式事务管理的支持,使得开发者可以通过注解或 XML 配置简单地实现事务控制,而无需显式编写繁琐的事务管理代码。
Spring 中事务的实现原理主要包括以下几个关键点:
3.1 事务管理器(Transaction Manager):
Spring 提供了 PlatformTransactionManager 接口及其多个实现类,用于与底层的数据源或持久化技术(如 JDBC、JPA、Hibernate 等)集成,管理事务的生命周期。不同的事务管理器实现支持不同的事务管理策略,如 JDBC 的 DataSourceTransactionManager、JPA 的 JpaTransactionManager 等。
3.2 事务管理的抽象层:
Spring 使用了 AOP(面向切面编程)和代理模式来实现事务管理的声明式支持。通过 AOP,Spring 在运行时动态地为带有 @Transactional 注解的方法生成代理对象,代理对象在方法调用前后添加事务管理逻辑,实现事务的开启、提交或回滚等操作。
3.3 事务传播行为(Propagation Behavior):
@Transactional 注解中的 propagation 属性用于指定事务的传播行为,定义了方法调用时事务如何传播到嵌套方法或者同一方法内的其他事务操作。Spring 提供了多种传播行为选项,如 Propagation.REQUIRED、Propagation.REQUIRES_NEW、Propagation.SUPPORTS 等,用于控制事务在不同方法间的传播和协调。
3.4 事务隔离级别(Isolation Level):
@Transactional 注解中的 isolation 属性用于指定事务的隔离级别,定义了事务对并发操作的可见性和影响范围。Spring 支持多种隔离级别,如 Isolation.DEFAULT、Isolation.READ_COMMITTED、Isolation.REPEATABLE_READ、Isolation.SERIALIZABLE 等,通过底层数据库支持来实现隔离级别的控制。
3.5 事务的切点(Pointcut)和通知(Advice):
Spring AOP 使用切点表达式(Pointcut Expression)来选择应用事务管理的方法,而事务管理本身则通过前置通知(Before Advice)、后置通知(After Returning Advice)、异常通知(After Throwing Advice)和最终通知(After Finally Advice)等方式来实现事务的各个阶段处理。
3.6 异常处理和事务回滚:
当被 @Transactional 注解标记的方法中抛出未被捕获的异常时,Spring 会自动回滚事务。这种机制确保了在方法执行失败或者异常情况下,数据库操作不会造成数据不一致或者丢失,保障了事务的一致性和可靠性。