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

什么是事务

事务是数据库管理系统中的一个关键概念,用于确保数据的完整性和可靠性。在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. 配置实体扫描

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

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    entityManagerFactoryRef = "entityManagerFactory",
    transactionManagerRef = "transactionManager",
    basePackages = {"com.example.domain"} // 实体类的包
)
public class DatabaseConfig {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder, DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.domain") // 实体类的包
                .persistenceUnit("default")
                .build();
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

4. 使用@Transactional注解

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

@Service
public class SomeService {

    @Autowired
    private SomeRepository someRepository;

    @Transactional
    public void someServiceMethod() {
        // 业务逻辑,涉及数据库操作
        someRepository.doSomething();
    }
}

5. 配置事务属性

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

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

6. 自定义事务管理器

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

@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注解中指定事务管理器和实体管理器工厂:

@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配置示例

@Configuration
public class DatabaseConfig {

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, DataSource dataSource) {
        return builder
                .dataSource(dataSource)
                .packages("com.example.domain") // 指定实体类所在的包
                .persistenceUnit("default")
                .build();
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

2. 配置TransactionTemplate

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

Java配置示例

@Service
public class SomeService {

    @Autowired
    private TransactionTemplate transactionTemplate; // Spring Boot会自动注入

    public void someServiceMethod() {
        // 使用TransactionTemplate执行事务
        transactionTemplate.execute(status -> {
            // 这里编写业务逻辑
            // 这些操作将被事务管理
            return null;
        });
    }
}

3. 设置事务属性

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

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

@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.mfbz.cn/a/585324.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

公文写作笔记

标题 最后一行的日期&#xff0c;后边占4个格子。两个数字占一格。落款单位在日期的正上方。 格式积累 内容&#xff1a; ①开头&#xff1a;缘由 ②主题&#xff1a;对策&#xff08;别人做得好&#xff0c;就借鉴&#xff09; ③结尾&#xff1a;简单的总结&#xff08;字…

LeetCode - 611.有效三角形个数

题目链接 LeetCode - 611. 有效三角形的个数 动画解释 代码解释 class Solution { public:int triangleNumber(vector<int>& nums) {sort(nums.begin(),nums.end());int cout 0;int fix nums.size()-1;while(fix>1){int left 0;int right fix-1;while(left &l…

rust将json字符串直接转为map对象或者hashmap对象

有些时候我们还真的不清楚返回的json数据里面到底有哪些数据&#xff0c;数据类型是什么等&#xff0c;这个时候就可以使用批处理的方式将json字符串转为一个对象&#xff0c;然后通过这个对象的get方法来获取json里面的数据。 pub async fn test_json(&self) {let json_st…

通过AI助手实现一个nas定时任务更新阿里云域名解析

一.通过AI助手实现一个ip-domain.py的脚本 起一个Python脚本&#xff0c;ip-domain.py&#xff1b;注意已安装Python3.的运行环境&#xff1b;将下面阿里云相关配置添加&#xff0c;注意这里引用了两个包&#xff0c;requests和alibabacloud_alidns20150109&#xff1b;执行前…

如何设计一套轻量级的批处理技术?

对于任何应用程序而言&#xff0c;可以说批处理都是一种基础设施类的技术组件。批处理技术应用非常广泛&#xff0c;数据报表、统计分析、定时任务等场景实际上都可以应用批处理技术。如何在不需要人工参与的情况下进行离线、自动、高效地进行复杂数据分析是批处理程序需要考虑…

如何消除SmartScreen“未知发布者”警告?

在互联网高速发展、应用程序遍地开花的当今时代&#xff0c;作为企业&#xff0c;我们通常会开发自己的应用程序来开展自己的业务&#xff0c;以便与客户建立更深入的联系。不少应用程序所有者可能会面临一个难题&#xff0c;那就是用户下载时&#xff0c;系统会弹出SmartScree…

可以在手机端运行的大模型标杆:微软发布第三代Phi-3系列模型,评测结果超过同等参数规模水平,包含三个版本,最小38亿,最高140亿参数

本文原文来自DataLearnerAI官方网站&#xff1a; 可以在手机端运行的大模型标杆&#xff1a;微软发布第三代Phi-3系列模型&#xff0c;评测结果超过同等参数规模水平&#xff0c;包含三个版本&#xff0c;最小38亿&#xff0c;最高140亿参数 | 数据学习者官方网站(Datalearner…

Docker-harbor——私有仓库部署与管理

目录 一、搭建本地私有仓库 1.下载Registry镜像 2.添加本地私有仓库配置 3.重启服务并运行Registry容器 4.容器的操作 4.1拉取Nginx镜像并为镜像打标签 4.2上传到私有仓库 4.3列出私有仓库所有镜像 4.4列出私有仓库的镜像的所有标签 5.先删除原有镜像再拉取私有仓库镜…

Python 全栈体系【四阶】(三十七)

第五章 深度学习 八、目标检测 3. 目标检测模型 3.1 R-CNN 系列 3.1.1 R-CNN 3.1.1.1 定义 R-CNN(全称 Regions with CNN features) &#xff0c;是 R-CNN 系列的第一代算法&#xff0c;其实没有过多的使用“深度学习”思想&#xff0c;而是将“深度学习”和传统的“计算…

华为配置mDNS网关示例(AP与AC间二层转发)

华为配置mDNS网关示例&#xff08;AP与AC间二层转发&#xff09; 组网图形 图1 配置mDNS网关组网图 组网需求配置思路操作步骤配置文件 组网需求 如图1所示&#xff0c;某企业的移动终端通过WLAN连接网络&#xff0c;AP_1和AP_2分别与AC之间采用二层转发。部门1和部门2分别属…

RakSmart站群服务器租用注意事项科普

随着互联网的飞速发展&#xff0c;站群运营成为越来越多企业和个人的选择。而RakSmart作为知名的服务器提供商&#xff0c;其站群服务器租用服务备受关注。在租用RakSmart站群服务器时&#xff0c;源库建议有一些关键的注意事项需要特别留意&#xff0c;以确保服务器的稳定运行…

SpringBoot学习之SpringBoot3集成OpenApi(三十八)

Springboot升级到Springboot3以后,就彻底放弃了对之前swagger的支持,转而重新支持最新的OpenApi,今天我们通过一个实例初步看看OpenApi和Swagger之间的区别. 一、POM依赖 我的POM文件如下,仅作参考: <?xml version="1.0" encoding="UTF-8"?>…

鼓吹开源无前途,Meta却开源了Llama 3模型,无需注册在线即可使用

Meta AI一直是人工智能领域开源领域的领导者&#xff0c;一边是OpenAI鼓吹闭源才是人工智能大模型的未来&#xff0c;但是Meta AI却开源了自己的Llama 3大模型&#xff0c;且Llama 3开源模型支持80亿与700亿参数&#xff0c;而未来更大的4000亿参数大模型还在继续训练中。其Lla…

webpack3升级webpack4遇到的各种问题汇总

webpack3升级webpack4遇到的各种问题汇总 问题1 var outputNamecompilation.mainTemplate.applyPluginWaterfull(asset-path,outputOptions.filename,{......)TypeError: compilation.mainTemplate.applyPluginsWaterfall is not a function解决方法 html-webpack-plugin 版…

机器学习实战-聚类算法

聚类算法是一种无监督学习的算法&#xff0c;用于将数据集中的数据分成不同的聚类或组。聚类算法是数据挖掘和机器学习领域中常见的技术之一&#xff0c;具有广泛的应用。 以下是聚类算法的一些知识点&#xff1a; 聚类算法的目的是将数据集划分为不同的组&#xff0c;使得组内…

【酱浦菌-爬虫项目】爬取百度文库文档

1. 首先&#xff0c;定义了一个变量url&#xff0c;指向百度文库的搜索接口 ‘https://wenku.baidu.com/gsearch/rec/pcviewdocrec’。 2. 然后&#xff0c;设置了请求参数data&#xff0c;包括文档ID&#xff08;docId&#xff09;和查询关键词&#xff08;query&#xff09;。…

【蓝桥杯C++A组省三 | 一场勇敢的征途与致19岁的信】

随着4.13西大四楼考场的倒计时结束… 就这样蓝桥杯落幕了 省三的名次既满足又不甘心&#xff0c;但又确乎说得上是19岁途中的又一枚勋章 从去年得知&#xff0c;纠结是否要报名、到寒假开始战战兢兢地准备、陆续开始创作博客&#xff0c;记录好题和成长……感谢你们的关注&…

Flask表单详解

Flask表单详解 概述跨站请求伪造保护表单类把表单渲染成HTML在视图函数中处理表单重定向和用户会话Flash消息 概述 尽管 Flask 的请求对象提供的信息足够用于处理 Web 表单&#xff0c;但有些任务很单调&#xff0c;而且要重复操作。比如&#xff0c;生成表单的 HTML 代码和验…

偏自相关系数的等价定义

第k个回归系数的值 原始定义

将两个YOLO格式的数据集合并,并保持相同类别

1. 需求分析 最近在做两个YOLO格式的数据集合并&#xff0c;第一个数据集包含了第二个数据集的类别&#xff0c;但是相应的类别id对应不住&#xff0c;需要修改第二个数据集的类别标签与第一个数据集对应住。 2. 修改第二个数据集标签对应 2.1 实现思路 导入所需的库&#x…
最新文章