Spring 事务管理:全面解析

Spring 框架是一款广受欢迎的 Java 开发框架,其强大的功能之一便是事务管理。事务管理在确保数据一致性和完整性方面至关重要。在这篇文章中,我们将深入探讨 Spring 事务管理,包括声明式事务管理、编程式事务管理,以及事务传播和隔离级别。

声明式事务管理

声明式事务管理是 Spring 框架的一个核心功能,它允许开发者通过配置和注解来管理事务,而不需要在代码中显式地进行事务管理操作。这种方式的主要优点是简化了代码,提高了可读性和可维护性。

使用注解进行声明式事务管理

Spring 提供了 @Transactional 注解,用于声明式事务管理。你只需在需要进行事务管理的方法或类上加上这个注解,Spring 就会自动处理事务的开始、提交和回滚。

import org.springframework.transaction.annotation.Transactional;@Service
public class UserService {@Transactionalpublic void createUser(User user) {// 保存用户userRepository.save(user);// 添加角色roleRepository.addRoleToUser(user.getId(), "ROLE_USER");}
}

在上述示例中,createUser 方法被 @Transactional 注解标记,这意味着该方法中的所有数据库操作将在同一个事务中进行。如果方法执行过程中出现异常,Spring 将自动回滚事务,确保数据一致性。

XML 配置

除了使用注解,Spring 还支持通过 XML 配置文件来声明事务。

<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="create*" propagation="REQUIRED"/></tx:attributes>
</tx:advice><aop:config><aop:pointcut id="userServiceOperation" expression="execution(* com.example.service.UserService.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="userServiceOperation"/>
</aop:config>
编程式事务管理

虽然声明式事务管理更为常用,但在某些复杂场景下,编程式事务管理可能更为合适。Spring 提供了 PlatformTransactionManager 接口,允许开发者在代码中手动管理事务。

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;@Service
public class ProductService {@Autowiredprivate PlatformTransactionManager transactionManager;public void addProduct(Product product) {TransactionDefinition def = new DefaultTransactionDefinition();TransactionStatus status = transactionManager.getTransaction(def);try {// 保存产品productRepository.save(product);// 保存库存inventoryRepository.addInventory(product.getId(), 100);transactionManager.commit(status);} catch (Exception e) {transactionManager.rollback(status);throw e;}}
}

在这个例子中,我们手动启动了一个事务,并在操作成功时提交事务,出现异常时回滚事务。虽然这种方法灵活性更高,但也增加了代码复杂性。

事务传播和隔离级别

Spring 事务管理的另一个重要方面是事务传播和隔离级别。了解和正确使用这些特性,可以帮助你处理更为复杂的事务场景。

事务传播

事务传播定义了在嵌套调用方法时,如何处理事务。Spring 提供了七种传播行为:

  1. PROPAGATION_REQUIRED:默认传播行为。如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  2. PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。
  3. PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  4. PROPAGATION_REQUIRES_NEW:创建一个新的事务。如果当前存在事务,则挂起当前事务。
  5. PROPAGATION_NOT_SUPPORTED:以非事务方式执行。如果当前存在事务,则挂起当前事务。
  6. PROPAGATION_NEVER:以非事务方式执行。如果当前存在事务,则抛出异常。
  7. PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新的事务。
事务隔离级别

事务隔离级别定义了一个事务与其他事务之间的隔离程度。常见的隔离级别有:

  1. ISOLATION_READ_UNCOMMITTED:允许读取未提交的数据,可能导致脏读、不可重复读和幻读。
  2. ISOLATION_READ_COMMITTED:只能读取已提交的数据,防止脏读,但可能导致不可重复读和幻读。
  3. ISOLATION_REPEATABLE_READ:防止脏读和不可重复读,但可能导致幻读。
  4. ISOLATION_SERIALIZABLE:最高的隔离级别,防止脏读、不可重复读和幻读,但性能较低。
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public void processOrder(Order order) {// 处理订单
}

在这个示例中,processOrder 方法被配置为在一个新的事务中执行,并且使用 SERIALIZABLE 隔离级别,确保最高的隔离程度。

总结

Spring 事务管理为我们提供了强大且灵活的工具,无论是通过声明式事务管理简化代码,还是通过编程式事务管理处理复杂场景,亦或是通过事务传播和隔离级别应对各种并发问题,都能帮助我们在开发过程中有效管理事务。

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

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

相关文章

CPP知识点记录总结

1、类的const成员函数 const成员函数的const 实际修饰的是该成员函数隐含的this指针&#xff0c;表明在该成员函数中不能对类的任何成员进行修改。 class A {void fun() const {// 常成员函数&#xff0c;在函数名后用const修饰} } 一文带你入门C类和对象【十万字详解&#…

谷歌正在试行人脸识别办公室安全系统

内容提要&#xff1a; &#x1f9ff;据美国消费者新闻与商业频道 CNBC 获悉&#xff0c;谷歌正在为其企业园区安全测试面部追踪技术。 &#x1f9ff;测试最初在华盛顿州柯克兰的一间办公室进行。 &#x1f9ff;一份内部文件称&#xff0c;谷歌的安全和弹性服务 (GSRS) 团队将…

【android】【adb shell】写一个shell脚本,监听进程pid变化

前言 当前业务&#xff0c;需要写一个脚本&#xff0c;不断监视com.android.phone 进程是否异常死掉 脚本 #!/system/bin/sh last_pid"" current_pid"" while(true){current_pidps -A | grep com.android.phone | awk {print $2}if [ -n "$current…

uni-appx,实现登录功能,弹窗功能。组件之间传值

这篇文章的内容使用组合式API实现的&#xff0c;只有弹窗部分有选择式API的写法介绍。如果想要看其他选择式API&#xff0c;还请下载官方的hello-uni-appx源码进行学习&#xff0c;查看。想要看组合式API的写法&#xff0c;请查看源码 hello-uvue。 hello-uni-appx源码 相比于…

Vue如何处理错误图片路径时换成另一张准备好的图片

在Vue中处理错误图片路径&#xff08;即当图片无法加载时&#xff09;并替换为另一张准备好的图片&#xff0c;可以通过几种方式实现。这里介绍两种常用的方法&#xff1a; 方法1&#xff1a;使用HTML的<img>标签的onerror事件 这是最直接的方法&#xff0c;可以直接在…

Vue + Element UI + JSEncrypt实现简单登录页面

安装依赖 npm install jsencrypt --save局部引入 import JSEncrypt from jsencrypt/bin/jsencrypt;登录页面index.vue <template><div class"loginbody"><div class"logindata"><div class"logintext"><h2>Wel…

Uncaught (in promise) RangeError: Offset is outside the bounds of the DataView

问题 通常发生在Failed to load resource: the server responded with a status of 404 (Not Found) 后&#xff0c;资源读取错误导致的问题。 解决 Failed to load resource: the server responded with a status of 404 (Not Found)_unity webgl failed to load resource:…

宝塔面板Nginx的https301跳转http

宝塔面板Nginx的https301跳转http&#xff1a; 登录宝塔面板&#xff1a;进入你的宝塔面板管理界面。 选择网站管理&#xff1a;在左侧菜单中&#xff0c;点击“网站”&#xff0c;然后选择你需要进行重定向的网站。 配置网站设置&#xff1a;在所选网站的管理界面中&#x…

Docker 容器网络互连 自定义网络 程序互相访问

介绍 在开发时候SpirngBoot应用需要连接Mysql数据库 &#xff0c;两个都在容器内&#xff0c;而容器都是独立的&#xff0c;这时需要配置容器内的网络互联。一旦两个容器加入了自定义网络就可以使用容器名互相访问。 Docker虚拟网卡 在安装Docker时候他会默认安装一个虚拟网…

LVS-DR群集

LVS-DR集群 LVS-DR(Linux Virtual Server DIrector Server)工作模式&#xff0c;是生产环境中最常用的一种工作模式。 LVS-DR工作原理 LVS-DR模式&#xff0c;Director Server作为群集的访问入口&#xff0c;不作为网关使用&#xff0c;节点DirectorServer与Real Server需要…

TensorRT-Int8量化详解

int8量化是利用int8乘法替换float32乘法实现性能加速的一种方法 对于常规模型有&#xff1a;y kx b&#xff0c;此时x、k、b都是float32, 对于kx的计算使用float32的乘法 对于int8模型有&#xff1a;y tofp32(toint8(k) * toint8(x)) b&#xff0c;其中int8 * int8结果为in…

2024.06.27 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流*裙 &#xff0c;内推/实习/校招汇总表格 1、提前批 | 禾赛科技2025届校招/提前批招聘 提前批 | 禾赛科技2025届校招提前批招聘 2、提前批 | CVTE2025校园招聘/提前批正式启动&#xff08;内推&#xff09; 提前批 | CVTE2025校园…

Python列表创建使用心得详解

概要 列表是Python中最常用的数据结构之一,它用于存储有序的元素集合。Python提供了多种方式来创建和操作列表,使得列表在数据处理、存储和操作中非常灵活。本文将详细介绍Python列表创建的各种技巧,包括基础创建方法、列表推导式、内置函数和高级创建技巧,并包含具体的示…

锁定依赖的秘诀:npm shrinkwrap命令深度解析

&#x1f512; 锁定依赖的秘诀&#xff1a;npm shrinkwrap命令深度解析 &#x1f512; 在JavaScript项目开发中&#xff0c;依赖管理是确保项目稳定性和可重复构建的关键环节。npm作为Node.js的包管理器&#xff0c;提供了npm shrinkwrap命令&#xff0c;用于锁定项目依赖的确…

什么是 qobject_cast?

前言 在 C++ 中,类型转换是一项常见的操作,比如将 int 转换为 char 或将 QString 用于 QMessageBox。但是,为什么我们需要将一个类转换为另一个类呢?本文将解释 qobject_cast 是什么,它的作用以及为什么需要类型转换。 dynamic_cast 和 qobject_cast 的概述 什么是 dyn…

初出茅庐的小李博客之C语言文件操作

C语言文件操作 在C语言中&#xff0c;文件操作主要是通过标准库函数来实现的。 今天有时间就来学习下一些常用的文件操作函数&#xff1a; C 语言提供了一个 FILE 数据结构&#xff0c;记录了操作一个文件所需要的信息。该结构定义在头文件stdio.h&#xff0c;所有文件操作函…

python库(3):Cerberus库

1 Cerberus简介 Cerberus 是一个Python数据验证库&#xff0c;设计用于验证数据结构的有效性和一致性。它提供了一种简单而强大的方式来定义和应用验证规则&#xff0c;特别适用于处理用户输入的验证、配置文件的检查以及API的参数验证等场景。下面将详细介绍 Cerberus 的特点…

伦敦金价格走势图的资金管理怎么进行?

要成熟地交易伦敦金价格走势图&#xff0c;其实并不是一件容易的事情。其一&#xff0c;我们在很多广告或者周边朋友的宣传之下&#xff0c;觉得它能够帮助我们很快之内实现很多的财富增值&#xff0c;其二&#xff0c;很多投资者觉得伦敦金交易虽然不错&#xff0c;但是风险好…

salesforce 批量下载文件为 attachment 时需要最后保存

future(callouttrue) public static void processCaseLinks(String caseId) {// 提取描述中的链接Case caseRecord [SELECT Id,Description FROM Case WHERE Id:caseId];List<String> links extractLinks(caseRecord.Description);List<Attachment> attachmentsT…

对象被优化以后才是高效的C++编程

课程总目录 文章目录 一、对象会调用哪些方法、对象优化的三个原则二、CMyString的代码问题三、四、添加带右值引用参数的拷贝构造和赋值函数五、CMyString在vector上的应用六、move移动语义和forward类型完美转发七、再聊vector容器使用对象过程中的优化 一、对象会调用哪些方…