【Spring】4.Spring的事务管理解析

ops/2024/9/23 8:14:02/

什么是事务

事务是数据库管理系统中的一个关键概念,用于确保数据的完整性和可靠性。在Spring框架中,事务通常指的是一段代码,这段代码要么完全执行,要么完全不执行,不会出现部分执行的情况。 Spring提供了事务管理的机制,允许开发者以声明式或编程式的方式来控制事务的边界和行为。

事务具有ACID属性,这确保了事务的可靠性:

  1. 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成,不会结束在中间某个点。
  2. 一致性(Consistency):事务必须使数据库从一个一致的状态转移到另一个一致的状态。
  3. 隔离性(Isolation):并发执行的事务之间不会互相影响,每个事务都像是独立执行。
  4. 持久性(Durability):一旦事务提交,则其结果永久保存在数据库中,即使系统发生故障也不会丢失。

Spring的事务管理主要有两种方式:

事务管理

1.声明式事务管理:

通过配置文件或注解来声明事务的边界和特性,利用AOP(面向切面编程)在方法执行前后添加事务管理的逻辑。
在Spring Boot中实现声明式事务管理,涉及到自动配置、自定义配置、事务属性的设置等多个方面。以下是详细的步骤和配置方法:

1. 添加依赖

确保项目中包含了Spring Boot的事务管理和数据库相关依赖。对于JPA,依赖如下:

Maven (pom.xml):

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- 数据库驱动依赖,例如MySQL --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- 其他业务依赖 -->
</dependencies>

Gradle (build.gradle):

dependencies {implementation 'org.springframework.boot:spring-boot-starter-data-jpa'implementation 'mysql:mysql-connector-java'// 其他业务依赖
}

2. 配置数据源

application.propertiesapplication.yml中配置数据库连接信息:

# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/your_db?useSSL=false
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

3. 配置实体扫描

创建一个配置类,用于指定实体类的扫描路径,以及配置事务管理器:

java">@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory",transactionManagerRef = "transactionManager",basePackages = {"com.example.domain"} // 实体类的包
)
public class DatabaseConfig {@Beanpublic LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource) {return builder.dataSource(dataSource).packages("com.example.domain") // 实体类的包.persistenceUnit("default").build();}@Beanpublic PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {return new JpaTransactionManager(entityManagerFactory);}
}

4. 使用@Transactional注解

在需要事务管理的类或方法上使用@Transactional注解:

java">@Service
public class SomeService {@Autowiredprivate SomeRepository someRepository;@Transactionalpublic void someServiceMethod() {// 业务逻辑,涉及数据库操作someRepository.doSomething();}
}

5. 配置事务属性

通过@Transactional注解的属性来配置传播行为、隔离级别、超时时间、只读属性和回滚规则:

java">@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.READ_COMMITTED,timeout = 30, // 超时时间,单位为秒readOnly = false,rollbackFor = Exception.class // 指定哪些异常会导致事务回滚
)
public void someServiceMethod() {// 业务逻辑
}

6. 自定义事务管理器

如果需要自定义事务管理器,可以在配置类中添加相应的@Bean方法:

java">@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {JpaTransactionManager transactionManager = new JpaTransactionManager();transactionManager.setEntityManagerFactory(entityManagerFactory);// 可以在这里设置其他属性,如超时时间return transactionManager;
}

7. 配置事务管理器属性

通过配置文件设置事务管理器的属性,例如JPA的事务超时时间:

# application.properties
spring.jpa.properties.hibernate.transaction.manager_lookup_class=org.hibernate.hql.internal.TransactionManagerLookup
spring.transaction.default_timeout=5 # 以秒为单位设置默认的事务超时时间

8. 多数据源事务管理

如果应用中使用了多个数据源,需要为每个数据源配置独立的事务管理器,并在@EnableJpaRepositories注解中指定事务管理器和实体管理器工厂:

java">@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactorySecondary",transactionManagerRef = "transactionManagerSecondary",basePackages = {"com.example.domain.secondary"}
)
public class SecondaryDatabaseConfig {@Bean(name = "entityManagerFactorySecondary")public LocalContainerEntityManagerFactoryBean getEntityManagerFactorySecondary() {// 配置第二个数据源的EntityManagerFactoryBean}@Bean(name = "transactionManagerSecondary")public PlatformTransactionManager getTransactionManagerSecondary(EntityManagerFactory entityManagerFactory) {// 配置第二个数据源的JpaTransactionManager}
}

通过上述步骤,就可以在Spring Boot应用中实现声明式事务管理了,并且可以根据业务需求配置不同的事务属性。Spring Boot的自动配置功能会根据你添加的依赖和配置来自动配置Spring的事务管理器,从而简化了事务管理的复杂性。

2.编程式事务管理:

通过代码直接管理事务的生命周期,如获取和释放事务资源,提交或回滚事务等。
在Spring Boot中实现编程式事务管理,你需要使用TransactionTemplate类。Spring Boot的自动配置机制会为你配置好事务管理器,但编程式事务管理不会自动应用,你需要显式地在你的代码中使用TransactionTemplate

以下是在Spring Boot中实现编程式事务管理的步骤:

1. 配置事务管理器

Spring Boot通常会自动配置事务管理器,但如果你想自定义配置,可以在配置类中添加一个PlatformTransactionManager的Bean。例如,如果你使用的是JPA,Spring Boot会默认配置一个JpaTransactionManager

Java配置示例

java">@Configuration
public class DatabaseConfig {@Beanpublic LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource) {return builder.dataSource(dataSource).packages("com.example.domain") // 指定实体类所在的包.persistenceUnit("default").build();}@Beanpublic PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {return new JpaTransactionManager(entityManagerFactory);}
}

2. 配置TransactionTemplate

在你的配置类或服务类中,创建一个TransactionTemplate的Bean,并注入你之前配置的PlatformTransactionManager

Java配置示例

java">@Service
public class SomeService {@Autowiredprivate TransactionTemplate transactionTemplate; // Spring Boot会自动注入public void someServiceMethod() {// 使用TransactionTemplate执行事务transactionTemplate.execute(status -> {// 这里编写业务逻辑// 这些操作将被事务管理return null;});}
}

3. 设置事务属性

通过TransactionTemplateexecute方法,你可以传递一个TransactionStatus的回调。虽然你不能直接设置传播行为和隔离级别,但你可以在事务管理器的配置中设置这些属性。

例如,对于DataSourceTransactionManager,你可以设置默认的隔离级别:

java">@Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource) {DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);transactionManager.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);return transactionManager;
}

4. 适应不同的业务场景

  • 读取操作:对于读取操作,如果不需要事务管理,可以使用PROPAGATION_NOT_SUPPORTEDPROPAGATION_NEVER
  • 写入操作:对于写入操作,默认使用PROPAGATION_REQUIRED
  • 嵌套事务:对于需要嵌套事务的场景,可以使用PROPAGATION_NESTED

由于编程式事务管理不使用注解,因此事务的传播行为和隔离级别通常在事务管理器的配置中设置。如果你需要更细粒度的控制,可能需要考虑使用声明式事务管理。
在Spring Boot中,推荐使用声明式事务管理,因为它更符合Spring的编程模型,并且易于使用。编程式事务管理通常用于那些不能使用声明式事务管理的场景。

3.事务的属性

在Spring框架中,事务属性定义了事务的特定行为,包括其传播行为、隔离级别、超时设置、只读标志以及回滚规则。以下是Spring支持的主要事务属性:

1. 传播行为(Propagation Behavior)

  • REQUIRED:如果存在一个事务,则加入该事务;如果不存在事务,则创建一个新的事务。
  • SUPPORTS:支持当前事务,如果没有事务则不创建。
  • MANDATORY:必须在一个事务中,否则抛出异常。
  • REQUIRES_NEW:总是创建一个新的事务。
  • NOT_SUPPORTED:不能在事务中执行,如果存在一个活动的事务,则将其挂起。
  • NESTED:如果支持嵌套事务,就创建一个嵌套事务。如果当前事务存在,则嵌套事务是当前事务的子事务。

2. 隔离级别(Isolation Level)

  • ISOLATION_DEFAULT:使用后端数据库的默认隔离级别。
  • ISOLATION_READ_UNCOMMITTED:读未提交。
  • ISOLATION_READ_COMMITTED:读已提交。
  • ISOLATION_REPEATABLE_READ:重复读。
  • ISOLATION_SERIALIZABLE:串行化。

3. 超时属性(Timeout)

  • 以秒为单位设置事务的超时时间。超过这个时间,事务将被回滚。

4. 只读属性(Read-Only)

  • 标记事务为只读事务,这可以给某些事务管理器提供优化的机会。

5. 回滚规则(Rollback Rules)

  • 定义哪些异常会导致事务回滚。可以使用rollbackFornoRollbackFor属性指定。

6. Phase(事务的阶段)

  • 指定事务应该在方法的执行阶段(例如,方法调用之前、调用之后、方法返回时或抛出异常时)。

7. 异步执行(Asynchronous Execution)

  • 在某些事务管理器中,可以配置事务的异步执行。

这些属性可以通过编程式事务管理或声明式事务管理来设置。在声明式事务管理中,通常使用@Transactional注解来设置这些属性,而在编程式事务管理中,则通过TransactionDefinition对象来设置。正确配置事务属性对于确保数据的一致性、隔离性和整体事务管理策略至关重要。理解这些属性及其对事务行为的影响是进行事务管理的关键。

工作原理

Spring中@Transactional注解的工作原理可以概括为以下几个步骤:

1. 注解驱动的事务管理启用

在Spring配置中通过@EnableTransactionManagement注解启用事务管理,这将使得Spring扫描并处理@Transactional注解。

2. 事务属性的配置

使用@Transactional注解标记方法或类,通过注解的参数定义事务的属性,如传播行为、隔离级别、超时时间、只读标志、回滚规则等。

3. 创建代理

Spring容器在创建Bean时,会检测到@Transactional注解。对于被注解的方法,Spring会通过AOP创建一个代理对象(可能是JDK动态代理或CGLIB代理),原始方法的调用会被这个代理对象所包装。

4. 代理对象的调用

当调用一个被@Transactional注解的方法时,实际上是调用了代理对象中的方法。在代理对象内部,Spring框架会在方法执行前后添加事务逻辑。

5. 事务的开始

在代理对象的方法调用之前,Spring会根据定义的事务属性开始一个新的事务或加入到已存在的事务中。

6. 业务逻辑的执行

执行被@Transactional注解的方法中的业务逻辑。

7. 事务的提交或回滚

  • 如果方法正常执行完成,Spring将提交事务。
  • 如果方法执行过程中抛出异常,并且该异常没有被注解的rollbackFor属性排除在外,Spring将回滚事务。

8. 清理

事务完成后,无论是提交还是回滚,Spring都会完成事务的清理工作,包括释放数据库连接等资源。

9. 事务管理器

在整个过程中,PlatformTransactionManager是一个关键的组件,它负责实际的事务管理操作,如获取TransactionStatus,以及根据运行时情况提交或回滚事务。

通过这个流程,@Transactional注解使得Spring能够以声明式的方式管理事务,让开发者可以专注于业务逻辑,而不必显式地处理事务的创建、提交和回滚。


http://www.ppmy.cn/ops/26112.html

相关文章

初学React基础

最近准备跟着黑马React学一下React&#xff0c;扩充一下技术面&#xff0c;打算还是以一边学习一边记笔记为主&#xff0c;进行学习&#xff01; 1. React介绍 1.1. React是什么&#xff1f; React是由FaceBook现在称&#xff08;Meta&#xff09;开发的开源 JavaScript 库&a…

基于EBAZ4205矿板的图像处理:03使用VIO调试输出HDMI视频图像

基于EBAZ4205矿板的图像处理&#xff1a;03使用VIO调试输出HDMI视频图像 在zynq调试时VIO是真的方便&#xff0c;特此写一篇博客记录一下 先看效果 项目简介 下面是我的BD设计&#xff0c;vtc用于生成时序&#xff0c;注意&#xff0c;2021.2的vivado的vtcIP是v6.2版本&…

SQLite如何处理CSV 虚拟表(三十七)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite的DBSTAT 虚拟表&#xff08;三十六&#xff09; 下一篇:SQLite的扩展函数Carray()表值函数(三十八) ​ RFC4180格式是一种文本文件格式&#xff0c;被用于表格数据间的交互&#xff0c;也可将表格数据转化…

python挑战10秒小程序

目录 一.前言 二.代码 三.分析 一.前言 >1.小程序开始时,会出现一个倒计时器,从10秒开始。 >2.玩家需要集中注意力并估计10秒钟过去的时间。 >3.当玩家认为10秒钟已经过去时,需要点击屏幕上的按钮。 >4.小程序会显示玩家的点击时间,以及与实际10秒钟的时间…

RS0108YQ20功能和参数介绍及高速数据传输中的优势

RS0108YQ20功能和参数介绍及高速数据传输中的优势-公司新闻-配芯易-深圳市亚泰盈科电子有限公司 RS0108YQ20是一款电平转换器&#xff0c;也称为电平移位器&#xff0c;它的主要功能是在不同的电源电压或逻辑电平之间提供双向信号转换。以下是RS0108YQ20的一些关键参数和功能特…

二叉树:数据结构的分形之美

1.树形结构 1.1概念 树是一种非线性的数据结构&#xff0c;它是由n(n>0)个有限结点组成一个具有层次关系的集合。把他叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就说它的根朝上&#xff0c;而叶朝下的。它具有以下的特点&#xff1a; 有一个特殊的节点&#xff0…

vue3的v-model在组件上几种用法

文章目录 父组件1、update和 : 拆开使用2、computed 计算属性方法3、defineModel (3.4) 官方推荐4、TS泛型用法(3.3) 父组件 <template><div><button click"dialogVisible !dialogVisible">打开/关闭</button><ModalComp v-model"…

将SSH密钥添加到GitHub账户

1、生成SSH密钥对&#xff1a; 首先&#xff0c;您需要在本地计算机上生成一个新的SSH密钥对。打开终端或命令提示符&#xff0c;然后运行以下命令。请确保替换your_emailexample.com为您GitHub账户关联的电子邮件地址。这里我们使用Ed25519算法&#xff0c;因为它既安全又高效…