SpringBoot 编程式事务使用

目录

  • 1. 简介
  • 2. TransactionTemplate 方式
  • 3. TransactionManager 方式
  • 4. 事务传播行为
  • 5. 事务隔离级别
  • 6. 最佳实践
  • 7. 常见问题与解决方案

1. 简介

编程式事务管理是通过编写代码来管理事务,相对于声明式事务(@Transactional注解),它提供了更细粒度的事务控制。在 SpringBoot 中,主要有两种实现方式:

  • 使用 TransactionTemplate
  • 直接使用 TransactionManager

2. TransactionTemplate 方式

TransactionTemplate 是最简单的编程式事务实现方式,它对底层事务 API 进行了封装,使用起来更加便捷。

2.1 基本配置

@Configuration
public class TransactionConfig {@Autowiredprivate PlatformTransactionManager transactionManager;@Beanpublic TransactionTemplate transactionTemplate() {TransactionTemplate template = new TransactionTemplate();template.setTransactionManager(transactionManager);// 设置默认的事务传播行为template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);// 设置默认的事务隔离级别template.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);// 设置默认超时时间template.setTimeout(30);return template;}
}

2.2 基本使用示例

@Service
@Slf4j
public class UserService {@Autowiredprivate TransactionTemplate transactionTemplate;@Autowiredprivate UserRepository userRepository;public User createUser(User user) {// 使用 execute 方法执行有返回值的事务操作return transactionTemplate.execute(status -> {try {User savedUser = userRepository.save(user);// 模拟其他操作updateUserProfile(savedUser);return savedUser;} catch (Exception e) {// 手动标记事务回滚status.setRollbackOnly();log.error("创建用户失败", e);throw new RuntimeException("创建用户失败", e);}});}public void batchCreateUsers(List<User> users) {// 使用 executeWithoutResult 方法执行无返回值的事务操作transactionTemplate.executeWithoutResult(status -> {try {for (User user : users) {userRepository.save(user);}} catch (Exception e) {status.setRollbackOnly();log.error("批量创建用户失败", e);throw new RuntimeException("批量创建用户失败", e);}});}
}

3. TransactionManager 方式

直接使用 TransactionManager 提供了更细粒度的事务控制,但使用起来相对复杂。

3.1 基本使用示例

@Service
@Slf4j
public class OrderService {@Autowiredprivate PlatformTransactionManager transactionManager;@Autowiredprivate OrderRepository orderRepository;public Order createOrder(Order order) {// 定义事务属性DefaultTransactionDefinition def = new DefaultTransactionDefinition();def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);def.setTimeout(30);// 获取事务状态TransactionStatus status = transactionManager.getTransaction(def);try {// 执行业务逻辑Order savedOrder = orderRepository.save(order);// 处理订单相关的其他操作processOrderDetails(savedOrder);// 提交事务transactionManager.commit(status);return savedOrder;} catch (Exception e) {// 回滚事务transactionManager.rollback(status);log.error("创建订单失败", e);throw new RuntimeException("创建订单失败", e);}}
}

3.2 嵌套事务示例

@Service
@Slf4j
public class PaymentService {@Autowiredprivate PlatformTransactionManager transactionManager;@Autowiredprivate PaymentRepository paymentRepository;public void processPayment(Payment payment) {// 外部事务定义DefaultTransactionDefinition outerDef = new DefaultTransactionDefinition();outerDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);TransactionStatus outerStatus = transactionManager.getTransaction(outerDef);try {// 外部事务操作paymentRepository.save(payment);// 内部事务定义DefaultTransactionDefinition innerDef = new DefaultTransactionDefinition();innerDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);TransactionStatus innerStatus = transactionManager.getTransaction(innerDef);try {// 执行内部事务操作processPaymentDetails(payment);transactionManager.commit(innerStatus);} catch (Exception e) {// 回滚内部事务transactionManager.rollback(innerStatus);log.error("支付详情处理失败", e);throw e;}// 提交外部事务transactionManager.commit(outerStatus);} catch (Exception e) {// 回滚外部事务transactionManager.rollback(outerStatus);log.error("支付处理失败", e);throw new RuntimeException("支付处理失败", e);}}
}

4. 事务传播行为

在编程式事务中,我们可以精确控制事务的传播行为:

@Service
public class TransactionPropagationExample {@Autowiredprivate TransactionTemplate transactionTemplate;public void demonstratePropagation() {// REQUIRED 传播行为TransactionTemplate requiredTemplate = new TransactionTemplate(transactionTemplate);requiredTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);// REQUIRES_NEW 传播行为TransactionTemplate requiresNewTemplate = new TransactionTemplate(transactionTemplate);requiresNewTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);// 嵌套使用不同的传播行为requiredTemplate.execute(outerStatus -> {// 外部事务逻辑requiresNewTemplate.execute(innerStatus -> {// 内部事务逻辑(新的事务)return null;});return null;});}
}

5. 事务隔离级别

示例展示如何设置不同的事务隔离级别:

@Service
public class TransactionIsolationExample {@Autowiredprivate PlatformTransactionManager transactionManager;public void demonstrateIsolation() {// 读已提交隔离级别DefaultTransactionDefinition readCommittedDef = new DefaultTransactionDefinition();readCommittedDef.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);TransactionStatus readCommittedStatus = transactionManager.getTransaction(readCommittedDef);try {// 业务逻辑transactionManager.commit(readCommittedStatus);} catch (Exception e) {transactionManager.rollback(readCommittedStatus);throw e;}// 可重复读隔离级别DefaultTransactionDefinition repeatableReadDef = new DefaultTransactionDefinition();repeatableReadDef.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);// ... 类似的事务处理逻辑}
}

6. 最佳实践

6.1 事务模板封装

创建一个通用的事务处理模板:

@Component
@Slf4j
public class TransactionHelper {@Autowiredprivate TransactionTemplate transactionTemplate;public <T> T executeInTransaction(TransactionCallback<T> action) {try {return transactionTemplate.execute(action);} catch (Exception e) {log.error("事务执行失败", e);throw new RuntimeException("事务执行失败", e);}}public void executeInTransactionWithoutResult(Consumer<TransactionStatus> action) {try {transactionTemplate.executeWithoutResult(action);} catch (Exception e) {log.error("事务执行失败", e);throw new RuntimeException("事务执行失败", e);}}
}// 使用示例
@Service
public class BusinessService {@Autowiredprivate TransactionHelper transactionHelper;public void doBusiness() {transactionHelper.executeInTransactionWithoutResult(status -> {// 业务逻辑});}
}

7. 常见问题与解决方案

7.1 事务超时处理

@Service
public class TimeoutExample {@Autowiredprivate TransactionTemplate transactionTemplate;public void handleTimeout() {TransactionTemplate timeoutTemplate = new TransactionTemplate(transactionTemplate);timeoutTemplate.setTimeout(5); // 设置5秒超时try {timeoutTemplate.execute(status -> {// 可能超时的业务逻辑return null;});} catch (TransactionTimedOutException e) {// 处理超时异常log.error("事务执行超时", e);throw new RuntimeException("事务执行超时", e);}}
}

7.2 异常处理最佳实践

@Service
public class ExceptionHandlingExample {@Autowiredprivate TransactionTemplate transactionTemplate;public void handleExceptions() {try {transactionTemplate.execute(status -> {try {// 业务逻辑return null;} catch (BusinessException e) {// 业务异常,标记回滚status.setRollbackOnly();throw e;} catch (Exception e) {// 其他异常,标记回滚status.setRollbackOnly();throw new RuntimeException("未预期的错误", e);}});} catch (Exception e) {// 统一异常处理handleException(e);}}private void handleException(Exception e) {if (e instanceof BusinessException) {// 处理业务异常log.warn("业务异常: {}", e.getMessage());} else {// 处理系统异常log.error("系统异常", e);}throw e;}
}

虽然编程式事务提供了更细粒度的控制,但在大多数情况下,声明式事务(@Transactional)可能是更好的选择。只有在需要特别精细的事务控制时,才考虑使用编程式事务。

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

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

相关文章

uniapp连接蓝牙操作(蓝牙设备地锁)

介绍&#xff1a; 本文采用uni-app框架来创建一个简单的用户界面&#xff0c;用于搜索、连接和发送命令给蓝牙设备。 1.打开蓝牙适配器 function openBluetooth() {uni.openBluetoothAdapter({success() {uni.offBluetoothDeviceFound();// 监听新设备发现事件uni.onBlueto…

web:pc端企业微信登录-vue版

官方文档&#xff1a;developer.work.weixin.qq.com/document/pa… 不需要调用ww.register&#xff0c;直接调用ww.createWWLoginPanel即可创建企业微信登录面板 - 文档 - 企业微信开发者中心 (qq.com) 引入 //通过 npm 引入 npm install wecom/jssdk import * as ww from we…

登陆harbor发现证书是错误的, 那么如何更新harbor的证书呢

Error response from daemon: Get "https://172.16.21.35/v2/": tls: failed to verify certificate: x509: certificate is valid for 127.0.0.1, ::1, 172.16.21.30, not 172.16.21.35 版本 v2.10.1-b7b88476 不需要从头看, 直接看最下面的成功的证书创建 这里面首…

外观模式的理解和实践

外观模式&#xff08;Facade Pattern&#xff09;是一种常用的软件设计模式&#xff0c;它提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口。该模式定义了一个高层的接口&#xff0c;使得子系统更容易使用。简单来说&#xff0c;外观模式就是通过引入一个外观角色…

excel使用笔记

1.工作表1计算工作表2某列的和 假设我们有两个工作表&#xff0c;分别命名为“Sheet1”和“Sheet2”&#xff0c;我们想要求和这两个工作表中A1到A**单元格的数据&#xff0c;可以在任意一个工作表的单元格中输入以下公式&#xff1a; SUM(Sheet1!A1:A10, Sheet2!A1:A10) SUM…

《应用导航设计:裂变式路由风暴来袭》——HarmonyOS开发项目时的Navigation路由奇妙使用

文章目录 应用导航设计引言概述场景示例基本实现推荐方案路由管理模块的实现页面跳转实现 业务实现中的关键点动态加载路由栈管理 应用导航设计 引言 在大型应用开发中&#xff0c;如何高效地设计应用导航&#xff0c;处理多模块间的路由跳转与解耦&#xff0c;始终是一个关键…

【腾讯云】AI驱动TDSQL-C Serveress 数据库技术实战营-如何是从0到1体验电商可视化分析小助手得统计功能,一句话就能输出目标统计图

欢迎来到《小5讲堂》 这是《腾讯云》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 背景效果图流程图创建数据库基本信息数据库配置设置密码控制台开启…

XSLT 编辑 XML

XSLT 编辑 XML 介绍 XSLT&#xff08;可扩展样式表语言转换&#xff09;是一种用于转换XML文档的语言。它允许开发人员将XML数据转换为其他格式&#xff0c;如HTML、PDF或纯文本。XSLT通过使用XPath查询来定位XML文档中的元素&#xff0c;并对这些元素应用转换规则。在本教程…

thinkphp8自带分页bootstrap

tp8引用的是bootstrap3.4.1这个版本&#xff1b; 前端结构&#xff1a; <ul class"pagination"><li><a href"/index.php?page4"></a></li><li><a href"/index.php?page1">1</a></li>…

win服务器的架设、windows server 2012 R2 系统的下载与安装使用

文章目录 windows server 2012 R2 系统的下载与安装使用1 windows server 2012 的下载2 打开 VMware 虚拟机软件&#xff08;1&#xff09;新建虚拟机&#xff08;2&#xff09;设置虚拟机&#xff08;3&#xff09;打开虚拟机 windows server 2012&#xff08;4&#xff09;进…

如何在谷歌浏览器中开启安全浏览

在数字化时代&#xff0c;网络安全变得愈发重要。作为全球最受欢迎的网络浏览器之一&#xff0c;谷歌浏览器提供了多种功能来保护用户的在线安全。本文将详细介绍如何在谷歌浏览器中开启安全浏览&#xff0c;并额外提供一些有用的页面滚动设置、地址栏快捷搜索和跟踪防护的相关…

djiango DRF的使用

djiango DRF的使用 一 、初始 DRF序列化环境安装环境配置数据模型定义定义DRF序列化模型对象 二 、DRF请求和响应请求对象&#xff08;Request objects&#xff09;响应对象&#xff08;Response objects&#xff09;状态码&#xff08;Status codes&#xff09;包装&#xff0…

如何使用 Python 连接 PostgreSQL 数据库?

在Python开发中&#xff0c;连接PostgreSQL数据库是一个常见的需求。 我们可以使用多种库来实现这一功能&#xff0c;其中最常用的是psycopg2。 下面我将详细介绍如何使用psycopg2来连接PostgreSQL数据库&#xff0c;并提供一些实际开发中的建议和注意事项。 1. 使用 psycop…

计算机网络-HTTP协议

HTTP HTTP是一种不保存状态&#xff0c;即无状态的协议。HTTP协议自身不对请求和响应之间的通信进行保存。为了保存状态因此后面也有一些技术产生比如Cookies技术。 HTTP是通过URI定位网上的资源&#xff0c;理论上将URI可以访问互联网上的任意资源。 如果不是访问特定的资源…

CTFHub 命令注入-综合练习(学习记录)

综合过滤练习 命令分隔符的绕过姿势 ; %0a %0d & 那我们使用%0a试试&#xff0c;发现ls命令被成功执行 /?ip127.0.0.1%0als 发现一个名为flag_is_here的文件夹和index.php的文件&#xff0c;那么我们还是使用cd命令进入到文件夹下 http://challenge-438c1c1fb670566b.sa…

前端 下载文件时如何处理后端返回的 文件流

在前端&#xff0c;处理文件下载通常涉及到接受一个 文件流&#xff08;Blob 或者 ArrayBuffer&#xff09;&#xff0c;然后将它转换成可以下载的链接。以下是实现前端文件下载并接受文件流的一些常见方法。 1. 使用 Blob 和 URL.createObjectURL 创建下载链接 假设后端返回…

HttpSevletRequest Body信息不能被多次读取的问题

在 Java Web 开发中&#xff0c;HTTP 请求体是客户端向服务器发送数据的主要载体&#xff0c;例如表单提交、JSON 数据等。当服务器收到请求后&#xff0c;通常通过 HttpServletRequest 类获取请求体的内容。然而&#xff0c;HTTP 请求体通常只能被读取一次。这是因为请求体使用…

ARM CCA机密计算安全模型之受保护内存

安全之安全(security)博客目录导读 目录 1、一般威胁模型 2、可能的缓解措施 3、CCA 使用外部内存 4、外部内存初始化 5、资产 6、基线内存保护配置文件 7、内存清理 8、额外的内存保护 许多 Realm 和 CCA 资产存储在外部内存中。本博客讨论针对基于内存攻击的缓解措施…

ubuntu升级python版本

Ubuntu升级Python版本 解压缩文件&#xff1a; 下载完成后&#xff0c;解压缩文件&#xff1a; tar -xf Python-3.12.0.tgz编译并安装&#xff1a; 进入解压后的目录&#xff0c;然后配置和安装Python&#xff1a; codecd Python-3.12.0 ./configure --enable-optimizations ma…

从Windows到Linux:跨平台数据库备份与还原

数据库的备份与还原 目录 引言备份 2.1 备份所有数据库2.2 备份单个数据库2.3 备份多个指定数据库 传输备份文件还原 4.1 还原所有数据库4.2 还原单个数据库4.3 还原多个指定数据库 注意事项拓展 1. 引言 在不同的操作系统间进行数据库迁移时&#xff0c;命令行工具是我们的…