spring事务管理快速入门(以转账为例)
spring事务管理(以转账为例)
概述
Spring事务管理提供了一种在应用程序中管理事务的机制,它抽象了底层的事务管理细节,使得开发者可以更加专注于业务逻辑的实现,而不必过多关心事务的处理。以下是Spring事务管理的一般概述:
-
事务的概念: 事务是一组操作,它们被看作一个不可分割的工作单元,要么全部执行成功,要么全部不执行。在数据库中,事务通常用于确保数据库的一致性和完整性。
-
Spring事务抽象: Spring提供了一个强大的事务管理抽象,它包括两个核心概念:事务管理器(TransactionManager) 和 事务定义(TransactionDefinition)。
-
事务管理器(TransactionManager): 是一个接口,它负责事务的启动、提交和回滚。Spring有多个实现类,可以适用于不同的事务管理场景。
-
事务定义(TransactionDefinition): 定义了事务的属性,如隔离级别、传播行为、超时等。Spring允许通过XML或注解的方式来配置事务的属性。
-
-
声明式事务管理: Spring支持声明式事务管理,这意味着你可以通过配置文件或注解的方式来声明事务,而不必在代码中显式编写事务管理的逻辑。
-
XML配置方式: 通过XML配置文件中的
和
元素来声明事务。 -
注解配置方式: 使用
@Transactional
注解来标注需要事务管理的方法,然后通过配置启用注解驱动事务管理。
-
-
编程式事务管理: 除了声明式事务管理外,Spring还支持编程式事务管理,这意味着你可以在代码中显式控制事务的开始、提交和回滚。
-
使用
TransactionTemplate
类: Spring提供了TransactionTemplate
类,它封装了事务的基本操作,你可以在代码中使用它来编程式地管理事务。
-
-
事务传播行为: 在Spring中,事务的传播行为(Transaction Propagation Behavior)定义了在一个事务方法被另一个事务方法调用时,应该如何处理事务。Spring定义了七种事务传播行为:
-
PROPAGATION_REQUIRED(默认):
-
如果当前存在事务,则加入该事务;如果不存在事务,则创建一个新的事务。这是最常见的传播行为。
-
-
PROPAGATION_SUPPORTS:
-
如果当前存在事务,则加入该事务;如果不存在事务,则以非事务的方式执行。
-
-
PROPAGATION_MANDATORY:
-
如果当前存在事务,则加入该事务;如果不存在事务,则抛出异常。要求外部调用方必须在事务中调用。
-
-
PROPAGATION_REQUIRES_NEW:
-
无论当前是否存在事务,都创建一个新的事务。如果有事务存在,将它挂起。
-
-
PROPAGATION_NOT_SUPPORTED:
-
以非事务的方式执行操作,如果当前存在事务,则将其挂起。
-
-
PROPAGATION_NEVER:
-
以非事务方式执行操作,如果当前存在事务,则抛出异常。
-
-
PROPAGATION_NESTED:
-
如果当前存在事务,则创建一个嵌套事务,并且它是当前事务的一个保存点(savepoint)。如果不存在事务,则行为类似于
PROPAGATION_REQUIRED
。
-
-
-
事务隔离级别: 事务隔离级别定义了在多个事务同时执行时,一个事务对数据的修改对其他事务的可见性程度。Spring定义了五个事务隔离级别,每个级别都有不同的特性和影响:
-
READ_UNCOMMITTED(读取未提交):
-
特性:允许一个事务读取另一个事务未提交的数据。
-
可能问题:脏读、不可重复读、幻读。
-
-
READ_COMMITTED(读取已提交):
-
特性:一个事务只能读取已经提交的另一个事务的数据。
-
可能问题:不可重复读、幻读。
-
-
REPEATABLE_READ(可重复读):
-
特性:确保事务可以多次从相同的数据集读取相同的数据,即使其他事务正在修改这些数据。
-
可能问题:幻读。
-
-
SERIALIZABLE(序列化):
-
特性:事务是串行执行的,所有的事务都按顺序依次执行,不允许并发执行。
-
可能问题:性能较低,但避免了脏读、不可重复读、幻读。
-
-
DEFAULT:
-
使用数据库默认的隔离级别,通常是数据库的默认配置。
-
-
-
事务回滚规则: Spring允许你配置哪些异常触发事务回滚,哪些异常不触发事务回滚。
-
分布式事务: Spring提供对分布式事务的支持,通过
JtaTransactionManager
实现了对JTA事务的集成。
PlatformTransactionManager概述
Spring的事务管理模块定义了一个平台事务管理器(PlatformTransactionManager)接口,该接口有多种实现,以适应不同的事务管理机制。主要的实现类包括:
-
DataSourceTransactionManager: 用于基于JDBC的事务管理,适用于关系型数据库,如MySQL、PostgreSQL等。
-
HibernateTransactionManager: 用于基于Hibernate的事务管理,适用于使用Hibernate框架的应用。
-
JtaTransactionManager: 用于基于Java EE的JTA(Java Transaction API)事务管理,适用于复杂的分布式事务场景。
-
JpaTransactionManager: 用于基于JPA(Java Persistence API)的事务管理,适用于使用JPA的应用。
-
WebLogicJtaTransactionManager: 专门用于WebLogic服务器上的JTA事务管理。
实体类domain层
package domain; public class account {private String name;private int gold; public account(String name, int gold) {this.name = name;this.gold = gold;} public account() {} public String getName() {return name;} public void setName(String name) {this.name = name;} public int getGold() {return gold;} public void setGold(int gold) {this.gold = gold;} @Overridepublic String toString() {return "account{" +"name='" + name + '\'' +", gold=" + gold +'}';} }
Dao层
接口
package dao; public interface accountDao {public void out(String man,int money);转出public void in(String man,int money);转入 }
实现类
package dao.Impl; import dao.accountDao; import org.springframework.jdbc.core.JdbcTemplate; public class accountImpl implements accountDao {JdbcTemplate jdbcTemplate ; • public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { • this.jdbcTemplate = jdbcTemplate; • } • @Override • public void out(String man, int money) { • jdbcTemplate.update("update account set gold=gold-? where name=?",money,man); • } • @Override • public void in(String man,int money) { • jdbcTemplate.update("update account set gold=gold+? where name=?",money,man); • } }
service层
接口
package dao; public interface accountDao {public void out(String man,int money);public void in(String man,int money); }
实现类
package service.Impl; import dao.accountDao; import service.accountService; public class accountServiceImpl implements accountService { accountDao accountdao; public void setAccountdao(accountDao accountdao) {this.accountdao = accountdao;} @Overridepublic void transfer(String outman, String inman, int money) {accountdao.out(outman,money);int i=1/0;accountdao.in(inman,money);} }
ApplicationContext.xml配置
<?xml version="1.0" encoding="UTF-8"?> <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"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><context:property-placeholder location="classpath:mysql.properties"></context:property-placeholder>配置数据源<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.Driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property></bean>配置jdbc模板<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="datasource"></property></bean><bean id="account" class="dao.Impl.accountImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean><bean id="accountService" class="service.Impl.accountServiceImpl"><property name="accountdao" ref="account"></property></bean> <!-- 配置事务管理平台--> 这里是基于springjdbc模板实现的所以用的是DataSource<bean id="transaction"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="datasource"></property></bean> <!-- 通知--><tx:advice id="myAdvice" transaction-manager="transaction"><tx:attributes> <!-- 哪些方法被增强--><tx:method name="transfer"isolation="READ_COMMITTED"propagation="REQUIRED" read-only="false" 因为转账肯定需要修改 所以不是只读/></tx:attributes></tx:advice> <!-- 配置事务的aop织入--><aop:config><aop:advisor advice-ref="myAdvice"pointcut="execution(* service.Impl.accountServiceImpl.*(..))"/></aop:config> </beans>
注解式声明式事务管理
xml配置
<?xml version="1.0" encoding="UTF-8"?> <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"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><context:property-placeholder location="classpath:mysql.properties"></context:property-placeholder>配置数据源<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.Driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property></bean>配置jdbc模板<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="datasource"></property></bean><bean id="account" class="dao.Impl.accountImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean><bean id="accountService" class="service.Impl.accountServiceImpl"><property name="accountdao" ref="account"></property></bean> <!-- 配置事务管理平台--> 这里是基于springjdbc模板实现的所以用的是DataSource<bean id="transaction"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="datasource"></property></bean>新加<tx:annotation-driven transaction-manager="transaction"></tx:annotation-driven><context:component-scan base-package="org.dao.Impl" /><context:component-scan base-package="org.service.Impl" />组件扫描<aop:aspectj-autoproxy></aop:aspectj-autoproxy> 启用 AspectJ 自动代理<context:annotation-config></context:annotation-config>启用注解驱动的配置,包括支持注解驱动的 AOP。在这个上下文中,主要是为了支持 @Transactional 注解,它用于启用声明式事务管理。在这个配置中,它会启用对带有 @Repository, @Service, @Controller 和其他注解的类的处理,以及其他一些注解相关的功能。
@Transactional() 等价于
<!-- 通知--> <tx:advice id="myAdvice" transaction-manager="transaction"> tx:attributes <!-- 哪些方法被增强--> <tx:method name="transfer" isolation="READ_COMMITTED" propagation="REQUIRED" read-only="false" 因为转账肯定需要修改 所以不是只读 /> /tx:attributes /tx:advice <!-- 配置事务的aop织入--> aop:config <aop:advisor advice-ref="myAdvice" pointcut="execution(* service.Impl.accountServiceImpl.*(..))"/> /aop:config </beans>
总结
转账这个例子 就是主动设计的错误是脏读 如果转账时出现网络 错误 一方转出了钱 ,一方没有收到钱,此时是不合理的,所以需要事务管理
相关文章:
spring事务管理快速入门(以转账为例)
spring事务管理(以转账为例) 概述 Spring事务管理提供了一种在应用程序中管理事务的机制,它抽象了底层的事务管理细节,使得开发者可以更加专注于业务逻辑的实现,而不必过多关心事务的处理。以下是Spring事务管理的一…...

如何在VS2022上的MFC项目中操作Excel(VS2010、VS2012、VS2015、VS2017、VS2019使用方法一样)
先决条件 本机安装office2003、2007、2010、2016及以后版本,总之必须安装office导入Excel库文件,导入方式可参考: 如何在vs2017及以前版本(vs2010、vs2015)上添加 添加类型库中的MFC类如何在vs2019及以后版本(如vs2022)上添加 添加ActiveX控…...

【Java8系列06】Java8数据计算
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

Andrioid T 实现充电动画(2)
Andrioid T 实现充电动画(2) 以MTK平台为例,实现充电动画 效果图 资源包 修改文件清单 system/vendor/mediatek/proprietary/packages/apps/SystemUI/res/layout/prize_charge_layout.xmlsystem/vendor/mediatek/proprietary/packages/ap…...

静态方法和属性的经典使用-单例设计模式
单例设计模式 一、设计模式二、单例模式1、饿汉式2、懒汉式3、区别 单例设计模式是静态方法和属性的经典使用。 一、设计模式 设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。设计模式就像是经典的棋谱,不同的棋局&…...

TCP七层协议
物理层 中间的物理链接可以是光缆、电缆、双绞线、无线电波。中间传的是电信号,即010101...这些二进制位。 比特(bit)是二进制(Binary Digit)的简称,电脑所有的信息都是二进制的,就是0和1组成的。 数据链路层 早期…...

规则引擎Drools使用,0基础入门规则引擎Drools(五)实战+决策表
文章目录 系列文章索引十、个人所得税计算器实战1、名词解释2、计算规则3、实现步骤 十一、信用卡申请实战1、计算规则2、实现 十二、保险产品准入规则实战1、决策表2、基于决策表的入门案例3、保险产品规则介绍4、实现步骤5、资料 系列文章索引 规则引擎Drools使用࿰…...

Java后端开发——MVC商品管理程序
Java后端开发——MVC商品管理程序 本篇文章内容主要有下面几个部分: MVC架构介绍项目环境搭建商品管理模块Servlet代码重构BaseServlet文件上传 MVC 是模型-视图-控制器(Model-View-Controller),它是一种设计模式,也…...

【隐私计算】VOLE (Vector Oblivious Linear Evaluation)学习笔记
近年来,VOLE(向量不经意线性评估)被用于构造各种高效安全多方计算协议,具有较低的通信复杂度。最近的CipherGPT则是基于VOLE对线性层进行计算。 1 VOLE总体设计 VOLE的功能如下,VOLE发送 Δ \Delta Δ和 b b b给send…...

国产linux单用户模式破解无密码登陆 (麒麟系统用户登录密码遗忘解决办法)
笔者手里有一批国产linu系统,目前开始用在日常的工作生产环境中,我这个老程序猿勉为其难的充当运维的或网管的角色。 国产linux系统常见的为麒麟Linux,统信UOS等,基本都是基于debian再开发的linux。 问题描述: 因为…...

GPT市场将取代插件商店 openAI已经关闭plugins申请,全部集成到GPTs(Actions)来连接现实世界,可以与物理世界互动了。
Actions使用了plugins的许多核心思想,也增加了新的特性。 ChatGPT的"Actions"与"Plugins"是OpenAI在GPT模型中引入的两种不同的功能扩展机制。这两种机制的目的是增强模型的功能,使其能够处理更多样化的任务和请求。下面是对两者的比…...
PHP定义的变量 常量 静态变量等储存在内存什么位置?
在 PHP 中,变量、常量和静态变量都存储在内存中。它们的存储位置和生命周期有所不同。 变量:PHP 中的变量是动态类型的,它们的值和类型可以随时改变。当 PHP 脚本执行时,会在内存中分配一块空间来存储变量的值,这个空…...

C#中GDI+绘图应用(柱形图、折线图和饼形图)
目录 一、柱形图 1.示例源码 2.生成效果 二、折线图 1.示例源码 2.生成效果 三、饼形图 1.示例源码 2.生成效果 GDI绘制的一些常用的图形,其中包括柱形图、折线图和饼形图。 一、柱形图 柱形图也称为条形图,是程序开发中比较常用的一种图表技术…...

连锁零售企业如何提高异地组网的稳定性?
随着数字化时代的到来,连锁零售企业面临着日益复杂和多样化的网络挑战。连锁零售企业是在不同地理位置拥有分支机构和零售店,可能同城或异地,需要确保各个地点之间的网络连接稳定和可靠。但由于不同地区的网络基础设施差异、网络延迟和带宽限…...

如何靠掌握自己的大数据打破信息流的壁垒?
在当今数字化时代,打造自己的私域流量已经成为商家乃至获取竞争优势的关键手段之一。通过掌握自己的大数据,可以更好地了解用户需求和市场趋势,优化产品和服务,从而打破信息流的壁垒。本文将就如何通过打造自己的私域流量并掌握大…...

LabVIEW绘制带有多个不同标尺的波形图
LabVIEW绘制带有多个不同标尺的波形图 通过在同一波形图上使用多个轴,可以使用不同的标尺绘制数据。请按照以下步骤操作。 将波形图或图表控件放在前面板上。 1. 右键点击您要创建多个标尺的轴,然后选择复制标尺。例如,如果要为一个…...
Oracle行转列,列转行使用实例
-----1.行转换为列 select a.fworkcenter as 车间,F1||-数量 as 类型, fspec as 规格 ,ftype as 前缀 , to_char(fdate,YYYY-MM-dd) as 日期, (case when a.fcode in (900,901) then to_char(fcount,fm90.990) else cast(fcount as varchar(20)) end) 值 , …...

056-第三代软件开发-软件打包
第三代软件开发-软件打包 文章目录 第三代软件开发-软件打包项目介绍软件打包1 下载 linuxdepoyqt 工具2 安装 linuxdepoyqt3 qmake配置4 打包程序 总结 关键字: Qt、 Qml、 linuxdeployqt、 Ubuntu、 AppImage 项目介绍 欢迎来到我们的 QML & C 项目&…...

C++相关闲碎记录(2)
1、误用shared_ptr int* p new int; shared_ptr<int> sp1(p); shared_ptr<int> sp2(p); //error // 通过原始指针两次创建shared_ptr是错误的shared_ptr<int> sp1(new int); shared_ptr<int> sp2(sp1); //ok 如果对C相关闲碎记录(1)中记录的shar…...

如何快速搭建一个大模型?简单的UI实现
🔥博客主页:真的睡不醒 🚀系列专栏:深度学习环境搭建、环境配置问题解决、自然语言处理、语音信号处理、项目开发 💘每日语录:相信自己,一路风景一路歌,人生之美,正在于…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...