Spring 事务的简单了解

news2024/11/28 20:54:43

目录

设计实现

工作原理

简单示例

隔离级别

事务传播机制



Spring框架提供了强大的事务管理支持,它允许开发者以声明性或编程性的方式来管理事务,从而保证数据的一致性和完整性。Spring事务管理的主要特点包括:

  1. 声明式事务管理: Spring支持使用注解或XML配置的方式来声明事务,使开发者可以在方法级别或类级别上定义事务的边界。

  2. 编程式事务管理: 如果需要更细粒度的控制,Spring也提供了编程式事务管理的方式,通过编写Java代码来控制事务的开始、提交、回滚等操作。

  3. 多数据源支持: Spring事务管理支持多个数据源之间的事务协调,例如,一个事务涉及多个数据库的操作。

  4. 分布式事务: Spring提供了对JTA(Java Transaction API)的支持,可以实现分布式事务,跨多个资源管理器(例如,多个数据库或消息队列)的事务一致性。

  5. 灵活的事务管理器: Spring支持多种事务管理器,包括JDBC事务管理器、Hibernate事务管理器、JTA事务管理器等,开发者可以根据需要选择合适的事务管理器。

  6. 嵌套事务: Spring允许嵌套事务,一个事务方法可以调用另一个事务方法,内层方法可以选择独立提交或回滚,而不会影响外层事务。

  7. 事务传播行为: Spring提供了不同的事务传播行为,如REQUIRED、REQUIRES_NEW、NESTED等,用于控制方法之间事务的关系。

设计实现

Spring事务管理的设计和实现原理基于AOP(面向切面编程)和反射技术。Spring框架通过AOP在运行时动态生成代理,实现事务管理的横切关注点,从而将事务管理从业务逻辑中解耦。

  1. AOP代理: Spring使用AOP代理技术来包装业务对象,以添加事务管理逻辑。这些代理对象在运行时拦截方法调用,并在方法执行前后执行额外的操作,如事务的开启、提交、回滚等。

  2. 切面(Aspect): 事务管理被抽象为一个切面,它包含了事务管理的逻辑。切面定义了在哪些地方执行事务管理操作,通常包括在方法执行前开启事务,在方法执行后提交事务,发生异常时回滚事务等。

  3. Advice: Advice是切面中的方法,它定义了在何时、何地执行事务管理操作。Spring框架中主要有以下几种类型的Advice:

    • Before:在方法执行前执行,用于开启事务。

    • After:在方法执行后执行,用于提交事务。

    • AfterReturning:在方法执行后执行,只有在方法成功执行后才会提交事务。

    • AfterThrowing:在方法抛出异常后执行,用于回滚事务。

  4. 切点(Pointcut): 切点是切面中定义的,用于定义在哪些方法上应用Advice。Spring提供了通配符表达式或自定义表达式来选择匹配的方法。

  5. 事务管理器(Transaction Manager): 事务管理器负责实际的事务管理操作,包括事务的开启、提交、回滚、事务的隔离级别、超时等。Spring支持多种事务管理器,如DataSourceTransactionManagerHibernateTransactionManagerJtaTransactionManager等,可以根据需要进行配置。

  6. 代理工厂(Proxy Factory): Spring框架使用代理工厂来创建代理对象,这些代理对象包含了事务管理的逻辑。Spring支持JDK动态代理和CGLIB代理,可以根据业务对象的类型和方法来选择合适的代理方式。

  7. 事务传播行为(Propagation): Spring允许定义事务传播行为,控制多个事务方法之间的事务关系。常见的传播行为包括REQUIRED、REQUIRES_NEW、NESTED等。

  8. 隔离级别(Isolation): 隔离级别定义了多个事务之间的隔离程度,包括READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE等级别。

  9. 只读标志(ReadOnly): 只读标志指示事务是否只读,只读事务可以提高性能,因为不需要锁定数据。

工作原理
  • 当业务方法被调用时,AOP代理会拦截方法执行。

  • 根据方法上的@Transactional注解或XML配置,决定是否需要开启新的事务。

  • 如果需要开启事务,事务管理器会开启一个新事务,并将事务与当前线程绑定。

  • 业务方法执行过程中,Advice会执行相应的事务管理操作,如提交或回滚。

  • 最终,事务管理器根据事务的状态,决定是提交还是回滚事务。

  • 事务在方法结束后被销毁,同时清理与当前线程的关联。

简单示例

主要涉及到了2个注解:

@EnableTransactionManagement:开启spring事务管理功能

@Transaction:将其加在需要spring管理事务的类、方法、接口上,只会对public方法有效。

  1. 首先,确保您的项目中包含了Spring的相关依赖,包括spring-corespring-tx

  2. 创建一个Spring配置文件,例如applicationContext.xml,并在其中配置数据源和事务管理器。以下是一个示例配置:

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context.xsd
               http://www.springframework.org/schema/tx
               http://www.springframework.org/schema/tx/spring-tx.xsd">
    ​
        <!-- 配置数据源 -->
        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://localhost:3306/mydb" />
            <property name="username" value="root" /> 
            <property name="password" value="123456" />
        </bean>
    ​
        <!-- 配置事务管理器 -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
    ​
        <!-- 开启注解驱动的事务管理 -->
        <tx:annotation-driven />
    </beans>
    ​
  3. 创建一个数据访问对象(DAO)来执行数据库操作。以下是一个示例的UserDAO类:

    @Repository
    public class UserDAO {
    ​
        @Autowired
        private JdbcTemplate jdbcTemplate;
    ​
        public void createUser(String username, String password) {
            String sql = "INSERT INTO users (username, password) VALUES (?, ?)";
            jdbcTemplate.update(sql, username, password);
        }
    }
  4. 创建一个服务类,用于调用DAO并管理事务。以下是一个示例的UserService类:

    @Service
    public class UserService {
    ​
        @Autowired
        private UserDAO userDAO;
    ​
        @Transactional
        public void createUserWithTransaction(String username, String password) {
            userDAO.createUser(username, password);
        }
    }
    ​
  5. 创建一个Spring Boot应用或Web应用,并将配置文件和服务类集成到应用中。编写入口执行:

    public class MainApp {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    ​
            UserService userService = context.getBean(UserService.class);
    ​
            userService.createUserWithTransaction("zhangsan", "123456");
        }
    }

    在此示例中,当createUserWithTransaction方法被调用时,Spring将自动管理事务的开启、提交和回滚。

隔离级别

隔离级别定义了多个事务并发执行时的数据隔离程度,通常包括以下几个级别,从低到高:

  1. READ UNCOMMITTED(读未提交): 允许一个事务读取另一个事务未提交的修改。这个隔离级别允许最低的隔离程度,可能导致脏读、不可重复读和幻读问题。

  2. READ COMMITTED(读已提交): 允许一个事务读取另一个事务已经提交的修改。这个级别避免了脏读问题,但仍可能发生不可重复读和幻读。

  3. REPEATABLE READ(可重复读): 保证在同一个事务中多次读取相同数据时,结果是一致的。这个级别避免了脏读和不可重复读,但仍可能发生幻读。

  4. SERIALIZABLE(串行化): 提供最高的隔离级别,确保每个事务都完全独立执行,不会发生任何并发问题。这个级别避免了脏读、不可重复读和幻读。

Spring中可使用@Transactional注解的isolation属性来指定隔离级别。例如:

@Transactional(isolation = Isolation.READ_COMMITTED)
事务传播机制

事务传播机制定义了当一个事务方法被另一个事务方法调用时,应该如何处理事务的行为。常见的事务传播行为包括:

  1. REQUIRED(默认): 如果当前没有事务,新建一个事务;如果当前已经存在一个事务,加入该事务。

  2. REQUIRES_NEW: 总是开启一个新的事务,挂起当前事务(如果存在)。

  3. SUPPORTS: 如果当前存在一个事务,就加入这个事务;如果没有事务,就以非事务方式执行。

  4. NOT_SUPPORTED: 以非事务方式执行,如果当前存在一个事务,就将其挂起。

  5. NEVER: 以非事务方式执行,如果当前存在一个事务,就抛出异常。

  6. MANDATORY: 必须在一个事务内执行,如果当前没有事务,就抛出异常。

  7. NESTED: 如果当前存在一个事务,就开启一个嵌套事务;如果当前没有事务,就行为类似于REQUIRED。

Spring中可使用@Transactional注解的propagation属性来指定事务传播行为。例如:

@Transactional(propagation = Propagation.REQUIRED)

组合使用隔离级别和事务传播机制可以根据具体的应用需求来管理事务,确保数据的一致性和完整性,同时提高性能和并发能力。事务的隔离级别和传播机制的选择需要根据具体的业务场景和需求来确定。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1096335.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言基础算法复习

003 斐波那契数列问题 #include<stdio.h> int main() {int i,f11,f21,f3,num;printf("%5d %5d",f1,f2);num2;for(i1; i<18; i){f3f1f2;f1f2;f2f3;num;printf("%5d",f3);if(num%40) printf("\n");}return 0; }//#输数斐波那契数列的前20…

k8s-12 存储之configmap

开启之后 先看集群是否正常 Configmap用于保存配置数据&#xff0c;以键值对形式存储configMap 资源提供了向 Pod 注入配置数据的方法旨在让镜像和配置文件解耦&#xff0c;以便实现镜像的可移植性和可复用性 典型的使用场景 填充环境变量的值 设置容器内的命令行参数 填充卷的…

百度OCR识别图片文本字符串——物联网上位机软件

一、开发背景 根据项目需求&#xff0c;我们需要完成LED显示屏实时显示歌词的效果。最优的方法是调用歌曲播放器的API获取歌词&#xff0c;但是由于这个开发资格不是很好申请&#xff0c;因此我们采用其他方案&#xff0c;即通过OCR识别获取歌词&#xff0c;并投射到LED显示屏上…

Potato靶机

信息搜集 设备发现 扫描端口 综合扫描 开放了80端口的HTTP服务和7120端口的SSH服务 目录扫描 扫描目录 看看这个info.php&#xff0c;发现只有php的版本信息&#xff0c;没有可以利用的注入点 SSH突破 hydra 爆破 考虑到 7120 端口是 ssh 服务&#xff0c;尝试利用 hydra …

【LeetCode热题100】--169.多数元素

169.多数元素 使用哈希表&#xff1a; class Solution {public int majorityElement(int[] nums) {int n nums.length;int m n/2;Map<Integer,Integer> map new HashMap<>(); //定义一个hashfor(int num:nums){Integer count map.get(num); //Map.get() 方法…

ARM架构的基本知识

ARM两种授权 体系结构授权, 一种硬件规范, 用来约定指令集, 芯片内部体系结构(内存管理, 高速缓存管理), 只约定每一条指令的格式, 行为规范, 参数, 客户根据这个规范自行设计与之兼容的处理器处理IP授权, ARM公司根据某个版本的体系结构设计处理器, 再把处理器设计方案授权给…

Java 全栈体系(三)

第一章 Java 基础语法 八、标识符 业内大多数程序员都在遵守阿里巴巴的命名规则。 1. 硬性要求 必须要这么做&#xff0c;否则代码会报错。 必须由数字、字母、下划线_、美元符号$组成。数字不能开头不能是关键字区分大小写的。 2. 软性建议 如果不这么做&#xff0c;代…

前后端数据导入导出Excel

一&#xff1a;导入 Excel有读取也便有写出&#xff0c;Hutool针对将数据写出到Excel做了封装。 原理 Hutool将Excel写出封装为ExcelWriter&#xff0c;原理为包装了Workbook对象&#xff0c;每次调用merge&#xff08;合并单元格&#xff09;或者write&#xff08;写出数据&…

【实操】基于ChatGPT构建知识库

前言 最近有些实践&#xff0c;因为后面要去研究fine-tune了&#xff0c;想着记录一下chatgpt向量数据库构建知识库的一些实操经验&#xff0c;不记我很快就忘了&#xff0c;哈哈。 首先&#xff0c;提一下为啥会出现向量数据库这个技术方案&#xff1f; 大家经过实践发现&…

10.2手动推导linux中file, cdev, inode之间的关系

是时候可以手动推导一下linux里面基类父类和子类的关系了 代码放最后把 简单说明版 详细流程 第一步注册驱动 cdev结构体能看做是一个基类,那么链表里面都是字符设备驱动的cdev连载一起,啥串口,lcd的,通过cdev->list_head连接 那cdev结构体里有主次设备号 第一步 使用r…

【机器学习】特征工程:从理论到实践的关键技巧

机器学习之特征工程实践技巧 1、引言2、了解特征工程2.1 机器学习2.2 特征工程 3、特征工程的思路4、特征工程的方法5、特征工程的实践6、总结 1、引言 小屌丝&#xff1a;鱼哥&#xff0c; 你不厚道~ 小鱼&#xff1a;啥情况&#xff1f; 小屌丝&#xff1a;你为啥不给我讲…

GMSH如何对STL模型再次划分网格

由于时间比较忙&#xff0c;一直未曾继续写博文&#xff0c;今天写一篇关于Gmsh对STL模型二次划分网格的测试。此项测试还不够完善&#xff0c;目前仅实现了STL模型的细分&#xff0c;效果还可以&#xff0c;在OSG下显示的效果如下&#xff1a; 一、原始STL显示效果&#xff0…

SVN服务端客户端安装配置

SVN服务端客户端安装配置 1、服务端下载安装1.1 软件下载1.2 软件安装 2、客户端下载安装2.1 软件下载2.2 软件安装2.2.1 安装2.2.2. 汉化 3、SVN配置3.1 SVN服务器端配置3. 2 SVN客户端配置 1、服务端下载安装 1.1 软件下载 百度网盘链接&#xff1a;VisualSVN-Server-5.3.0…

YApi和Swagger接口管理

这篇博客针对苍穹外卖而写 YApi 之前的官网&#xff1a;yapi.smart-xwork.cn 由于之前的网址访问不了&#xff0c;现在我用的是这个网址&#xff1a;YApi Pro-高效、易用、功能强大的可视化接口管理平台 登录之后如下 创建两个工作空间 用户端接口也是如法炮制 Swagger 使用…

SSM - Springboot - MyBatis-Plus 全栈体系(二十七)

第六章 SpringBoot 二、SpringBoot3 配置文件 1. 统一配置管理概述 SpringBoot 工程下&#xff0c;进行统一的配置管理&#xff0c;你想设置的任何参数&#xff08;端口号、项目根路径、数据库连接信息等等)都集中到一个固定位置和命名的配置文件&#xff08;application.pro…

九、K8S之Ingress

Ingress 一、Ingress 概念 Ingress提供从集群外部到集群内服务的Http路由&#xff0c;流量路由由 Ingress 资源所定义的规则来控制。通过配置&#xff0c;Ingress可为Service提供外部可访问的URL&#xff0c;对其流量作负载均衡&#xff0c;代理转发。Ingress 的使用可以大大…

基于EtherCAT的机器人多轴同步运动控制

随着工业自动化的发展&#xff0c;机器人在生产线上的应用越来越广泛。为了实现高效、精确的运动控制&#xff0c;机器人的多轴运动必须能够实现同步操作&#xff0c;它能够提高机器人的运动精度和稳定性&#xff0c;实现更高效的生产线操作。同时&#xff0c;它也为机器人的协…

力扣刷题 day45:10-15

1&#xff0c;整数拆分 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 方法一&#xff1a;动态规划 #方法一&#xff1a;动态规划 def integerBreak…

2022最新版-李宏毅机器学习深度学习课程-P16 Loss可能影响网络训练失败softmax与sigmoid

一、实例回顾 分类的例子在前几讲中已详细分析&#xff0c;此处略过。 二、softmax与sigmoid 此处要明白&#xff01;softmax和sigmoid的区别和联系 Softmax函数和Sigmoid函数的区别与联系 - 知乎 (zhihu.com) Sigmoid 多标签分类问题多个正确答案非独占输出&#xff08;例如…

四叉堆在GO中的应用-定时任务timer

堆作为必须掌握的数据结构之一&#xff0c;在众多场景中也得到了广泛的应用。 比较典型的&#xff0c;如java中的优先队列PriorityQueue、算法中的TOP-K问题、最短路径Dijkstra算法等&#xff0c;在这些经典应用中堆都担任着灵魂般的角色。 理论基础 binary heap 再一起回忆…