当前位置: 首页 > news >正文

Spring事务-两种开启事务管理的方式:基于注解的声明式事务管理、基于编程式的事务管理

Spring事务-两种开启事务管理的方式

      • 1、前期准备
      • 2、基于注解的声明式事务管理
      • 3、基于编程式的事务管理
      • 4、声明式事务失效的情况

例子:假设有一个银行转账的业务,其中涉及到从一个账户转钱到另一个账户。在这个业务中,我们需要保证要么两个账户都成功更新,要么都不更新,以避免出现数据不一致的情况。以下是基于注解的声明式事务管理和编程式事务管理的示例:

1、前期准备

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId><version>2.5.4</version></dependency>

首先是实体类 Account

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;@Entity
@TableName("account")
public class Account {@Idprivate Long id;    //银行账户的唯一标识符private String accountNumber;   //银行账户的账号,用于唯一标识一个账户private double balance; //银行账户的余额,表示账户当前的可用资金数量// getters and setters
}

在这里插入图片描述

在这里插入图片描述

然后是 AccountRepository

import org.springframework.data.jpa.repository.JpaRepository;
@Mapper
public interface AccountRepository extends JpaRepository<Account, Long> {Account findByAccountNumber(String accountNumber);
}

然后是控制器类 BankController

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;@RestController
public class BankController {@Autowiredprivate BankService bankService;@PostMapping("/transfer")public String transfer(@RequestBody TransferRequest request) {bankService.transfer(request.getFromAccount(), request.getToAccount(), request.getAmount());return "Transfer successful";}
}

接下来是请求体类 TransferRequest

public class TransferRequest {private String fromAccount;private String toAccount;private double amount;// getters and setters
}

2、基于注解的声明式事务管理

这种方式使用注解来定义事务,通过在需要进行事务管理的方法上添加相应的注解来标识事务的边界和属性

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class BankService {@Autowiredprivate AccountRepository accountRepository;@Transactionalpublic void transfer(String fromAccount, String toAccount, double amount) {Account from = accountRepository.findByAccountNumber(fromAccount);Account to = accountRepository.findByAccountNumber(toAccount);from.setBalance(from.getBalance() - amount);to.setBalance(to.getBalance() + amount);accountRepository.save(from);int i = 1/0;accountRepository.save(to);}
}

在这里插入图片描述
报错,事务回滚
在这里插入图片描述

在这里插入图片描述

在上面的示例中,@Transactional注解被用于标记transfer方法。这表示transfer方法将被Spring框架管理事务。如果该方法执行过程中发生异常,Spring会回滚所有的数据库操作,以保证数据的一致性。

3、基于编程式的事务管理

编程式事务管理是一种通过编程方式手动控制事务的管理过程。与声明式事务管理相比,它不依赖于特定的注解或配置,而是在代码中显式地编写事务管理逻辑在编程式事务管理中,开发人员需要手动管理事务的开始、提交、回滚等过程

编程式事务管理的主要原理包括以下几个方面:

  1. 事务定义(Transaction Definition): 在编程式事务管理中,首先需要定义事务的属性,包括事务的传播行为、隔离级别、超时时间等。这些定义将决定事务的行为。

  2. 事务管理器(Transaction Manager): 事务管理器负责实际管理事务,包括事务的开始、提交、回滚等操作。在编程式事务管理中,通常需要手动获取事务管理器,并调用其方法来管理事务。

  3. 事务的控制: 在编程式事务管理中,开发人员需要显式地控制事务的开始、提交、回滚等过程。这通常通过调用事务管理器的方法来实现,如获取事务、提交事务、回滚事务等。

  4. 异常处理: 在事务管理过程中,可能会出现各种异常情况。开发人员需要适当地处理这些异常,例如在捕获到异常时执行事务的回滚操作,以保证数据的一致性。

  5. 事务边界: 在编程式事务管理中,需要明确定义事务的边界,即事务开始和结束的位置。通常事务的边界由业务逻辑决定,在业务逻辑的开始处开启事务,在结束处提交或回滚事务。

首先需要定义事务管理器 Bean: 在 Spring Boot 应用程序的配置类中,使用 @Bean 注解定义一个名为 transactionManager 的 DataSourceTransactionManager Bean。确保该 Bean 使用了正确的数据源。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;@Configuration
public class TransactionConfig {@Beanpublic DataSourceTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}

service

import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class BankService {@Autowiredprivate AccountRepository accountRepository;@Autowiredprivate DataSourceTransactionManager transactionManager;public void transfer(String fromAccount, String toAccount, double amount) {DefaultTransactionDefinition def = new DefaultTransactionDefinition();def.setName("transaction-1");def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);TransactionStatus status = transactionManager.getTransaction(def);try {Account from = accountRepository.findByAccountNumber(fromAccount);Account to = accountRepository.findByAccountNumber(toAccount);from.setBalance(from.getBalance() - amount);to.setBalance(to.getBalance() + amount);accountRepository.save(from);accountRepository.save(to);transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);throw e;}}
}

在这里插入图片描述

在这里插入图片描述

在这个示例中,我们直接使用了DataSourceTransactionManager来手动管理事务。我们首先定义了一个事务的定义(DefaultTransactionDefinition),然后使用该定义来开启一个事务。如果执行过程中发生异常,我们手动回滚事务;如果一切正常,则手动提交事务。

4、声明式事务失效的情况

  • @Transactional 应用在非 public 修饰的方法上
  • @Transactional 注解属性 propagation 设置错误
  • @Transactional 注解属性 rollbackFor 设置错误
  • 同一个类中方法调用,导致@Transactional失效
  • 异常被catch捕获导致@Transactional失效
  • 数据库引擎不支持事务

笔者有空再针对这几种情况进行说明

相关文章:

Spring事务-两种开启事务管理的方式:基于注解的声明式事务管理、基于编程式的事务管理

Spring事务-两种开启事务管理的方式 1、前期准备2、基于注解的声明式事务管理3、基于编程式的事务管理4、声明式事务失效的情况 例子&#xff1a;假设有一个银行转账的业务&#xff0c;其中涉及到从一个账户转钱到另一个账户。在这个业务中&#xff0c;我们需要保证要么两个账户…...

OC 技术 苹果内购

一直觉得自己写的不是技术&#xff0c;而是情怀&#xff0c;一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的&#xff0c;希望我的这条路能让你们少走弯路&#xff0c;希望我能帮你们抹去知识的蒙尘&#xff0c;希望我能帮你们理清知识的脉络&#xff0…...

云原生周刊:Kubernetes v1.30 一瞥 | 2024.3.25

开源项目推荐 Retina Retina 是一个与云无关的开源 Kubernetes 网络可观测平台&#xff0c;它提供了一个用于监控应用程序运行状况、网络运行状况和安全性的集中中心。它为集群网络管理员、集群安全管理员和 DevOps 工程师提供可操作的见解&#xff0c;帮助他们了解 DevOps、…...

2016年认证杯SPSSPRO杯数学建模D题(第一阶段)NBA是否有必要设立四分线解题全过程文档及程序

2016年认证杯SPSSPRO杯数学建模 D题 NBA是否有必要设立四分线 原题再现 NBA 联盟从 1946 年成立到今天&#xff0c;一路上经历过无数次规则上的变迁。有顺应民意、皆大欢喜的&#xff0c;比如 1973 年在技术统计中增加了抢断和盖帽数据&#xff1b;有应运而生、力挽狂澜的&am…...

EdgeGallery开发指南

API接口 简介 EdgeGallery支持第三方业务系统通过北向接口网关调用EdgeGallery的业务接口。调用流程如下图所示&#xff08;融合前端edgegallery-fe包含融合前端界面以及北向接口网关功能&#xff0c;通过浏览器访问时打开的是融合前端的界面&#xff0c;通过IP:Port/urlPref…...

ubuntu arm qt 读取execl xls表格数据

一&#xff0c;ubuntu linux pc编译读取xls的库 1&#xff0c;安装libxls(读取xls文件 电脑版) 确保你已经安装了基本的编译工具&#xff0c;如gcc和make。如果没有安装&#xff0c;可以使用以下命令安装&#xff1a; sudo apt-update sudo apt-get install build-essentia…...

STM32 使用gcc编译介绍

文章目录 前言1. keil5下的默认编译工具链用的是哪个2. Arm编译工具链和GCC编译工具链有什么区别吗&#xff1f;3. Gcc交叉编译工具链的命名规范4. 怎么下载gcc-arm编译工具链参考资料 前言 我们在STM32上进行开发时&#xff0c;一般都是基于Keil5进行编译下载&#xff0c;Kei…...

FPGA之组合逻辑与时序逻辑

数字逻辑电路根据逻辑功能的不同&#xff0c;可以分成两大类&#xff1a;组合逻辑电路和时序逻辑电路&#xff0c;这两种电路结构是FPGA编程常用到的&#xff0c;掌握这两种电路结构是学习FPGA的基本要求。 1.组合逻辑电路 组合逻辑电路概念&#xff1a;任意时刻的输出仅仅取决…...

git clone没有权限的解决方法

一般情况 git clone时没有权限&#xff0c;一般是因为在代码库平台上没有配置本地电脑的id_rsa.pub 只要配置上&#xff0c;一般就可以正常下载了。 非一般情况 但是也有即使配置了id_rsa.pub后&#xff0c;仍然无法clone代码的情况。如下 原因 这种情况是因为ssh客户端…...

Redis 的内存回收策略

Redis的内存回收策略用于处理过期数据和内存溢出情况&#xff0c;确保系统稳定性和性能。作为一个高性能的键值存储系统&#xff0c;它通过内存回收策略来维护内存的高效使用 主要包括过期删除策略和内存淘汰策略。 过期删除策略&#xff1a; Redis的过期删除策略是通过设置…...

小程序富文本图片宽度自适应

解决这个问题 创建一个util.js文件,图片的最大宽度设置为100%就行了 function formatRichText(html) {let newContent html.replace(/\<img/gi, <img style"max-width:100%;height:auto;display:block;");return newContent; }module.exports {formatRichT…...

安装redis时候修改过的配置文件

只要是石头&#xff0c;到哪里都不会发光的 bind 绑定主机某个网卡对应的IP地址&#xff0c;如果某个主机有两个网卡A和B&#xff0c;那么绑定了A&#xff0c;通过B连接就会无法访问protected-mode 保护模式 Yes为只能本地访问port 启动的端口号pidfile pid存放的位置&#xff…...

Stable Diffusion 本地部署教程

Stable Diffusion是一种用于构建和部署机器学习模型的开源工具。以下是在本地环境中部署 Stable Diffusion 的基本步骤: 步骤 1: 准备环境 确保你的系统中已经安装了以下软件和工具: Python(建议使用 Python 3.x)pip(Python 包管理工具)Docker(可选,用于容器化部署)…...

sql如何增加数据

在MySQL中增加数据主要是通过INSERT INTO SQL语句来实现的。以下是对插入语句的详细介绍以及举例说明&#xff1a; 1、插入语句的基本格式&#xff1a; 1INSERT INTO table_name (column1, column2, ..., columnN) 2VALUES (value1, value2, ..., valueN); table_name&#x…...

智慧交通(代码实现案例)

1.项目简介 目标: 了解智慧交通项目的架构知道智慧交通项目中的模块能够完成智慧交通项目的环境搭建 该项目是智慧交通项目&#xff0c;通过该项目掌握计算机视觉的方法在交通领域的相关应用&#xff0c;包括车道线检测的方法&#xff0c;多目标车辆追踪及流量统计方法&#…...

LeetCode 面试经典150题 205.同构字符串

题目&#xff1a; 给定两个字符串 s 和 t &#xff0c;判断它们是否是同构的。 如果 s 中的字符可以按某种映射关系替换得到 t &#xff0c;那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符&#xff0c;同时不改变字符的顺序。不同字符不能映射到同一个字…...

存内计算:释放潜能的黑科技

什么是存内计算&#xff1f; 存内计算技术是一种新型的计算架构&#xff0c;它将存储器和计算单元融合在一起&#xff0c;以实现高效的数据处理。存内计算技术的优势在于能够消除数据搬运的延迟和功耗&#xff0c;从而提高计算效率和能效比。目前&#xff0c;存内计算技术正处…...

CentOS Stream 8系统配置阿里云YUM源

Linux运维工具-ywtool 目录 一.系统环境二.修改yum文件2.1 CentOS-Stream-AppStream.repo2.2 CentOS-Stream-BaseOS.repo2.3 CentOS-Stream-Extras.repo 三.只有一个配置文件四.其他知识4.1 如果想要启用其他源,修改文件配置:enabled14.2 国内源链接 一.系统环境 CentOS Strea…...

MySQL Explain 优化参数详细介绍

Explain 是什么? Explain命令用于分析SQL查询的执行计划&#xff0c;帮助优化查询语句和索引选择。 Explain是MySQL提供的一个非常有用的工具&#xff0c;它能够帮助数据库管理员和开发者理解SQL查询是如何被数据库执行的。通过在SELECT语句前加上EXPLAIN关键字&#xff0c;…...

代码随想录Day58:每日温度、下一个更大元素 I

每日温度 class Solution { public:vector<int> dailyTemperatures(vector<int>& temperatures) {stack<int> st;vector<int> result(temperatures.size(), 0);for(int i 0; i < temperatures.size(); i){while(!st.empty() && tempe…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

作者&#xff1a;来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布&#xff0c;Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明&#xff0c;Elastic 作为 …...