Spring 核心技术解析【纯干货版】- VIII:Spring 数据访问模块 Spring-Tx 模块精讲
在企业级开发中,事务管理是保障数据一致性和完整性的重要手段。Spring 作为 Java 生态中广泛使用的框架,其事务管理模块(Spring-Tx)不仅提供了强大的功能,还极大地简化了开发者在不同技术栈中的事务处理工作。无论是编程式事务,还是声明式事务,Spring 都以其灵活性和易用性满足了各种场景需求。
本篇文章将从理论到实践,深入解析 Spring-Tx 模块的核心技术与使用方式,并通过代码示例帮助您更高效地掌握事务管理。希望通过本篇内容,您能对 Spring 的事务管理有一个全面且深入的理解。
文章目录
1、Spring-Tx 模块介绍
1.1、Spring-Tx 模块概述
Spring Tx 模块,是 Spring 中处理事务管理的模块,其中 TX 全称为 Spring Transaction Management。
Spring Tx 模块的设计目标是为了让应用程序中的事务管理变得更加简单、统一和灵活。不论是在传统的 JDBC 环境下,还是在使用 ORM(如 Hibernate)的环境中,它都能提供一致的编程模型来处理事务。
1.2、Spring-Tx 模块依赖
Spring-Tx 模块的依赖有两个,分别是 Spring-Beans 模块和 Spring-Core 模块。
其中 Spring Beans 模块是对 Spring Bean 进行定义,实现 IOC 基础功能的模块。而 Spring-Core 是 Spring 中的基础模块,它提供了框架运行所必需的核心功能。
需要注意的是,Spring-Tx 对事务的实现主要基于 Spring AOP 的原理,但是其本身并不依赖于 Spring 相关 AOP 模块的实现,而是通过自身达成这一效果的。
1.3、Spring-Tx 模块作用
Spring-Tx 模块为开发者提供了一套高效、灵活的事务处理机制,适用于各种持久化技术和事务场景。
2、事务介绍
概括来讲,事务是一个由有限操作集合组成的逻辑单元。事务操作包含两个目的,数据一致以及操作隔离。数据一致是指事务提交时保证事务内的所有操作都成功完成,并且更改永久生效;事务回滚时,保证能够恢复到事务执行之前的状态。操作隔离则是指多个同时执行的事务之间应该相互独立,互不影响。
事务是一个比较广泛的概念,事务管理资源除了我们熟知的数据库外,还可以包含消息队列、文件系统等。当然,一般来说,我们说的事务单指"数据库事务"。
3、Spring 事务
Spring 事务有编程式事务和声明式事务两种实现方式:
- 编程式事务是通过编写代码来管理事务的提交、回滚、以及事务的边界。这意味着开发者需要在代码中显式地调用事务的开始、提交和回滚。
- 声明式事务是通过配置来管理事务,您可以使用注解或XML配置来定义事务的边界和属性,而无需显式编写事务管理的代码。
3.1、Spring 编程式事务
编程式事务就是通过硬编码的方式使用 Spring 中提供的事务相关的类来控制事务。主要有 2 种用法:
- 方式1:通过
PlatformTransactionManager
控制事务 - 方式2:通过
TransactionTemplate
控制事务
3.1.1、通过 PlatformTransactionManager 控制事务
这种是最原始的方式,代码量比较大,后面其他方式都是对这种方式的封装。这种方式需要手动管理事务的定义、开启、提交和回滚。它的优点是灵活性高,但代码相对繁琐。
示例代码:
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
public class TransactionService1 {
private final PlatformTransactionManager transactionManager;
public TransactionService1(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public void executeTransaction() {
// 创建事务定义
TransactionDefinition def = new DefaultTransactionDefinition();
// 开启事务
TransactionStatus status = transactionManager.getTransaction(def);
try {
// 业务逻辑
performBusinessLogic();
// 提交事务
transactionManager.commit(status);
} catch (Exception e) {
// 出现异常,回滚事务
transactionManager.rollback(status);
throw e;
}
}
private void performBusinessLogic() {
// 模拟业务逻辑
System.out.println("Executing business logic...");
// 模拟异常
if (true) {
throw new RuntimeException("Error occurred");
}
}
}
优缺点:
- 优点:灵活性高,适合对事务有特殊控制需求的场景。
- 缺点:代码量多,增加复杂性,容易遗漏回滚或提交操作。
3.1.2、通过 TransactionTemplate 控制事务
TransactionTemplate
是 Spring 提供的事务管理工具类,它封装了事务的开启、提交和回滚逻辑,简化了代码。开发者只需关注业务逻辑的实现。
示例代码:
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
public class TransactionService2 {
private final TransactionTemplate transactionTemplate;
public TransactionService2(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
public void executeTransaction() {
// 使用 TransactionTemplate 执行事务
transactionTemplate.execute((TransactionCallback<Void>) status -> {
// 业务逻辑
performBusinessLogic();
return null; // 返回结果,如果有返回值需要修改 Void 类型
});
}
private void performBusinessLogic() {
// 模拟业务逻辑
System.out.println("Executing business logic...");
// 模拟异常
if (true) {
throw new RuntimeException("Error occurred");
}
}
}
优缺点:
- 优点:代码简洁,开发者无需手动管理事务的提交和回滚。
- 缺点:灵活性比直接使用
PlatformTransactionManager
略低。
3.2、Spring 声明式事务
3.2.1、声明式事务
声明式事务是指使用注解或xml配置的方式来控制事务的提交和回滚。开发者只需要添加配置即可,具体事务的实现由第三方框架实现,避免我们直接进行事务操作。
Spring 提供了 @EnableTransactionManagement
注解在配置类(启动类)上启用支持事务,此时 Spring 会自动扫描具有 @Transactional
注解的类和方法。该注解相当于 xml 配置方式的 <tx:annotation-driven />
。通过设置 mode
属性,决定使用 Spring 代理,还是 ASPECTJ 扩展。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY; // 代理模式
int order() default Ordered.LOWEST_PRECEDENCE; // LOWEST_PRECEDENCE最低优先级,所以在执行链的最外面,而自己实现的AOP拦截器优先级都高于事务,所以被嵌套在里面,越贴近业务代码。
}
3.2.2、@Transactional 注解的使用
@Transactional
注解可以应用于类和方法 。声明类时,该注解 默认作用于类和子类的所有方法,应用于 public
方法才有效 ;父类方法要加入同等级别的注解,需要单独声明。
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
@AliasFor("transactionManager")
String value() default "";
// 用来确定目标事务管理器
@AliasFor("value")
String transactionManager() default "";
// 事务的传播,默认Propagation.REQUIRED
Propagation propagation() default Propagation.REQUIRED;
// 事务隔离级别,默认是Isolation.DEFAULT
Isolation isolation() default Isolation.DEFAULT;
// 事务超时时间,默认是-1
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
// 指定事务是否为只读事务,默认为false,仅仅是个提示
boolean readOnly() default false;
// 标识能触发事务回滚的异常类型,默认是RuntimeException和Error,不包含检查异常。
Class<? extends Throwable>[] rollbackFor() default {};
// 标识哪些异常不需要回滚事务
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
String[] rollbackForClassName() default {};
}
其中,isolation
和 timeout
两个属性仅对新启动的事务有效,专为 Propagation.REQUIRED
和 Propagation.REQUIRES_NEW
使用而设计。
3.2.3、事务的传播行为 - Propagation
Propagation 定义了事务的传播,一共有 7 种级别。
public enum Propagation {
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
NEVER(TransactionDefinition.PROPAGATION_NEVER),
NESTED(TransactionDefinition.PROPAGATION_NESTED);
private final int value;
Propagation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
-
REQUIRED
:使用当前的事务,如果当前没有事务,则自己新建一个事务,子方法是必须运行在一个事务中的;如果当前存在事务,则加入这个事务,成为一个整体。 -
SUPPORTS
:如果当前有事务,则使用事务;如果当前没有事务,则不使用事务。多用于查询。 -
MANDATORY
:传播属性强制必须存在一个事务,如果不存在,则会抛出异常。 -
REQUIRES_NEW
:如果当前有事务,则挂起该事务,并且自己创建一个新的事务给自己使用;如果当前没有事务,则同REQUIRED
-
NOT_SUPPORTED
:如果当前有事务,则把事务挂起,自己不使用事务运行数据库操作 -
NEVER
:如果当前有事务存在,则抛出异常 -
NESTED
:如果当前存在事务,则开启子事务(嵌套事务);如果当前没有事务,则同REQUIRED
。但是 如果主事务提交,则会携带子事务一起提交。如果主事务回滚,则子事务会一起回滚。 相反,子事务异常,则父事务可以回滚或不回滚(trycatch)。
3.2.4、事务的隔离级别-Isolation
Isolation 定义了事务的隔离级别,一共有 5 种。
public enum Isolation {
DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);
private final int value;
Isolation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
Spring 事务隔离级别共有 5 种,隔离级别的设置依赖当前数据库是否支持。
DEFAULT
:使用当前数据库的默认隔离级别。例如Oracle是READ_COMMITED,MySQL是READ_REPEATED。READ_UNCOMMITED
:可导致脏读、不可重复读、幻读。READ_COMMITTED
:阻止脏读,可导致不可重复读、幻读。REPEATABLE_READ
:阻止脏读和不可重复读,可导致幻读。SERIALIZABLE
:该级别下事务顺序执行,阻止上面的缺陷,开销很大。
X、后记
事务管理在现代应用中扮演着至关重要的角色,尤其是在分布式系统、微服务架构日益普及的今天,如何高效地管理数据一致性成为每个开发者都需要面对的挑战。Spring-Tx 模块以其简单、优雅且强大的特性,为事务管理提供了一站式的解决方案。
通过本篇文章的学习,相信您已经掌握了 Spring-Tx 的基本原理、配置方式以及编程式与声明式事务的具体用法。在实际项目中,选择合适的事务管理方式,合理配置事务属性,将显著提升系统的稳定性和可靠性。
期待您在今后的开发中,能够灵活运用 Spring-Tx 模块,为项目带来更高的效率和更好的性能。
原文地址:https://blog.csdn.net/m0_74824517/article/details/145272450
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!