SSM框架学习——Spring事务管理

news2024/11/26 19:48:53

Spring事务管理

概念

事务(Transaction)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么都不执行,是一个不可分割的工作单元

事务有如下特性:

  • 原子性
  • 隔离性
  • 一致性
  • 持久性

如果多个事务同时操作同一批数据,则会引发并发异常,设置不同的隔离级别可以解决这些问题。事务的隔离级别如下

隔离界别从小到大,安全性越高,但效率就越低。

事务的传播行为是指在同一个方法中,不同操作前后所使用的事务。传播行为可以控制是否需要创建事务以及如何创建事务,Spring默认传播行为是REQUIRED。

事务的管理方式主要分为两种:

  • 编程式事务管理:通过编写代码实现的事务管理,包括定义事务的开始、正常执行后的事务提交和异常时的事务回滚
  • 声明式事务管理:通过AOP技术实现的事务管理,主要思想是将事务作为一个“切面”代码单独编写,然后通过AOP技术将事务管理的“切面”植入到业务目标类中

为了解耦,我们一般用后者。

声明式事务管理

基于XML

Spring的声明式事务管理可以通过两种方式来实现,一种是基于XML的方式,另一种是基于注解的方式。

基于XML方式的声明式事务是在配置文件中通过<tx:advice>元素配置事务规则来实现的。当配置了事务的增强处理后,就可以通过编写的AOP配置,让Spring自动对目标生成代理。其属性如下。

基于注解

我们更关心基于注解的方式,下面用代码来了解下

我们用之前的top.cairbin.test3项目

app.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"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/tx
  http://www.springframework.org/schema/tx/spring-tx.xsd
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- 指定需要扫描的包,使注解生效 -->
	<context:component-scan
		base-package="top.cairbin.test3" />
	<!-- 配置dataSource -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<!--数据库驱动 -->
		<property name="driverClassName"
			value="com.mysql.jdbc.Driver" />
		<!--连接数据库的url -->
		<property name="url"
			value="jdbc:mysql://localhost:3306/db_javaee" />
		<!--连接数据库的用户名 -->
		<property name="username" value="db_javaee" />
		<!--连接数据库的密码 -->
		<property name="password" value="dbjavaeepassword" />
	</bean>
	<!-- 2配置JDBC模板 -->
	<bean id="jdbcTemplate"
		class="org.springframework.jdbc.core.JdbcTemplate">
		<!-- 默认必须使用数据源 -->
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	
	<bean id="transactionManager" class=
     "org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>	
    <!-- 注册事务管理器驱动 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

IAccountDao中声明方法

public void transfer(String outUser,String inUser,Double money);

AccountDao类中添加方法及注解

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public void transfer(String outUser, String inUser, Double money) {
    // 收款时,收款用户的余额=现有余额+所汇金额
    this.jdbcTemplate.update("update account set balance = balance +? "
            + "where username = ?",money, inUser);
    // 模拟系统运行时的突发性问题
    int i = 1/0;
    // 汇款时,汇款用户的余额=现有余额-所汇金额
    this.jdbcTemplate.update("update account set balance = balance-? "
            + "where username = ?",money, outUser);
}

JdbcTemplateTest测试类中添加测试方法

@Test
public void transTest(){		
    accountDao.transfer("lisi", "zhangsan", 100.0);
    // 输出提示信息
    System.out.println("转账成功!");
}

运行程序前向数据库中插入两条记录,我们使用终端或者sqlyog连接数据库,我这里以Mac的终端为例

mysql -u db_javaee -p

注意这里,我们用的不再是root账户,而是之前创建的db_javaee

输入密码dbjavaeepassword,如果你之前设置的与我不一样这里换成你的密码

输入密码的时候是不显示密码内容的,敲击回车,如果界面跟我下面差不多就说明成功了

后面来写SQL语句,首先把数据库切换到db_javaee下面

USE db_javaee;

如果出现Database changed提示则表示成功。

我们先来查看下之前创建的Account

SELECT * FROM account;

这是我的表里面的内容,你的应该与我不太一样,不过不影响接下来的操作。

我们使用一下语句来插入两条数据

INSERT INTO account(id,username,balance) VALUES(17,'zhangsan',100);
INSERT INTO account(id,username,balance) VALUES(18,'lisi',200);

成功的话会有提示

来看下目前表里的数据

SELECT * FROM account;

接下来我们回到Eclipse IDE,运行我们的代码

运行结果如下

不出意外的话该出意外了,注意看左边的transTest()方法竟然报错,那是正常的,因为我们public void transfer(String outUser, String inUser, Double money);代码写了int i = 1/0;这种语句来模拟报错。

我们到数据库中查看数据

SELECT * FROM account;

很显然数据没有啥变化,我们将transfer方法中的int i = 1/0;删掉试试。注意方法名称,别搞错了。

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public void transfer(String outUser, String inUser, Double money) {
    // 收款时,收款用户的余额=现有余额+所汇金额
    this.jdbcTemplate.update("update account set balance = balance +? "
            + "where username = ?",money, inUser);
    // 模拟系统运行时的突发性问题
    // int i = 1/0;
    // 汇款时,汇款用户的余额=现有余额-所汇金额
    this.jdbcTemplate.update("update account set balance = balance-? "
            + "where username = ?",money, outUser);
}

运行一下,发现控制台输出转账成功!

回到数据库查看下

SELECT * FROM account;

下图是操作前后两次的对比,上面是转账成功之前的,后面是转账成功之后的。

数据显然是发生变化了!

问题

到了这里,你可能会有疑问,敲了这么多的代码,我们还不断地进行测试、查看数据库,到底是想干什么。

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
public void transfer(String outUser, String inUser, Double money) {
    // 收款时,收款用户的余额=现有余额+所汇金额
    this.jdbcTemplate.update("update account set balance = balance +? "
            + "where username = ?",money, inUser);
    // 模拟系统运行时的突发性问题
    int i = 1/0;
    // 汇款时,汇款用户的余额=现有余额-所汇金额
    this.jdbcTemplate.update("update account set balance = balance-? "
            + "where username = ?",money, outUser);
}

我们看看上方的代码。**在前面提到过事务的特性是原子的,也就是不可分割的。**倘若我们没有事务,当this.jdbcTemplate.update(...);这条语句执行的时候,数据库就已经更新了,而int i = 1/0;却出现了一个突发性问题,按理来说我们转账transfer这一方法不应该成立才对,而数据库中的记录的确发生了变动。

如果你是一个恶意用户,然后你发现了这一漏洞,向银行存款,每次存款失败代码异常银行都退回你钱,然后你不断重复这个操作就可以使你的账户余额不断增加,然而你实际上并没有存一分钱进去,这显然是不合理的!

然而我们有了事务,就不会发生这种情况了,因为对于transfer这一操作是不可分割成小操作的,也就是说对于方法里面的东西要么全成功,要么全失败回滚,不可能出现部分成功部分失败这种情况。

结束

Spring初步这一部分就到此为止了,你会发现对于数据库操作在代码里嵌入SQL语句是很麻烦而且不可靠的,如果不做好过滤,用户提交一段包含SQL语句的字符串就有可能利用你的权限操作数据库,还会有安全问题,所以接下来我们将学习MyBatis这个框架。

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

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

相关文章

有单片机基础,准备过一遍freertos,之后再学linux

应届生我觉得继续把单片机深入一下比较好。 站在公司的角度思考一下&#xff0c;个人觉得应该有以下结论&#xff1a; 1 大公司具备技术资金等优势&#xff0c;因此喜欢学历好&#xff0c;理论扎实能够攻坚的人。倾向于培养各个领域的专家&#xff0c;共同构建自己产品的竞争…

全流程基于GIS、python机器学习技术的地质灾害风险评价与信息化建库实践应用

将结合项目实践案例和科研论文成果进行讲解。入门篇&#xff0c;ArcGIS软件的快速入门与GIS数据源的获取与理解&#xff1b;方法篇&#xff0c;致灾因子提取方法、灾害危险性因子分析指标体系的建立方法和灾害危险性评价模型构建方法&#xff1b;拓展篇&#xff0c;GIS在灾害重…

基于“遥感+”蓝碳储量估算、红树林信息提取实践技术应用与科研论文写作教程

原文链接&#xff1a;基于“遥感”蓝碳储量估算、红树林信息提取实践技术应用与科研论文写作教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247599633&idx5&sn1398cde523f9c5e036e4d478fc1d3388&chksmfa8207f6cdf58ee0a3a2bf652e7ac5cf65636b05f9e…

探索数据库-------MYSQL故障排除与优化

目录 mysql逻辑架构图 一、MySQL 数据库故障 1.1 MySQL 单实例故障排查 1.1.1故障现象 1 1.1.2故障现象 2 1.1.3故障现象 3 1.1.4故障现象 4 1.1.5故障现象 5 1.1.6故障现象 6 1.1.7故障现象 7 1.1.8故障现象 8 1.2MySQL 主从故障排查 1.2.1故障现象 1 1.2.2故障…

【PDF技巧】PDF文件打开密码,如何设置?

想要给PDF文件设置打开密码是保护文件内容不被他人查看的好选择&#xff0c;但是因为每个PDF编辑器不同&#xff0c;大家的简单设置方法都有些不同&#xff0c;不过今天小编给大家分享一个通用的PDF文件设置打开密码的方法给大家。 打开pdf编辑器&#xff0c;我们点击工具栏中…

6000000IOPS!FASS×kunpeng920全新突破

实测数据详见下文 网络环境 前端和后端网均采用100GE网络&#xff0c;管理网采用1Gbps以太网。 前端网和后端网通过不同网段隔离&#xff0c;与管理网物理隔离。 软硬件配置 存储端配置&#xff1a; 客户端配置&#xff1a; 软件配置&#xff1a; 存储集群配置&#xff1a; …

【区块链 链外交易】SoK Off The Chain Transactions

SoK Off The Chain Transactions 摘要 本文对区块链进行了简单介绍,分析目前区块链的缺点——交易吞吐量和速度慢的原因,在此基础上引出解决此问题的方法,也是本轮将要论述的主题——链外交易。之后介绍了链外交易的基本概念和结构,并对两种类型的链外交易:通道和信任链…

PMAT:使用低覆盖度HiFi测序数据的高效植物线粒体组装工具包

PMAT: an efficient plant mitogenome assembly toolkit using low-coverage HiFi sequencing data &#xff0c;一篇关于线粒体组装工具包的文献 PMAT&#xff1a;使用低覆盖度HiFi测序数据的高效植物线粒体组装工具包 植物的完整线粒体基因组&#xff08;mitogenomes&#x…

软件项目经理面试必备PMP知识 | 软件项目管理面试题目

1. 在项目管理中&#xff0c;客户可以控制范围、时间和成本中的哪些方面&#xff1f; 范围、时间和成本构成了项目管理中的三角关系。当其中一项发生变化时&#xff0c;很可能会影响到其他两项。项目管理的核心在于在保证质量的前提下&#xff0c;寻求这三者之间的最佳平衡。作…

Metasequoia 4 for Mac v4.8.7激活版 水杉3D建模器

Metasequoia 4 for Mac是一款强大的3D水杉建模软件&#xff0c;该应用程序设法提供一组强大的功能&#xff0c;并通过非常友好的界面提供。运行水杉有几种模式&#xff0c;即初学者&#xff0c;建模&#xff08;字符串&#xff09;&#xff0c;建模&#xff08;图标&#xff09…

搭建端到端检索式问答系统

问答系统(Question Answering System, QA)是信息检索系统的一种高级形式&#xff0c;它能用准确、简洁的自然语言回答用户用自然语言提出的问题。问答系统的应用空间十分广&#xff0c;包括搜索引擎&#xff0c;小度音响等智能硬件&#xff0c;聊天机器人&#xff0c;以及政府、…

golang语言系列:学习路线图

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 golang语言系列 文章&#xff0c;主要展示golang语言学习的全路线图 参考&#xff1a;https://github.com/darius-khll/golang-developer-roadmap/blob/master/i18n/zh-CN/ReadMe-zh-CN.md

【攻防世界】file_include (PHP伪协议+过滤器)

打开题目环境&#xff1a; 进行PHP代码审计&#xff0c;发现这是一个文件包含漏洞。 我们尝试利用PHP伪协议中的 php://filter来读取 check.php 中的内容。 构造payload 并提交&#xff1a; 发现payload被过滤掉了&#xff0c;我们就需要尝试使用不同的转换器。 PHP各类转换…

鸿蒙OS开发问题:【尺寸适配算法】

背景 如何在HarmonyOS 系统上出设计稿&#xff1f; 问题1: 为什么要计算虚拟高度&#xff0c;即 virtualHeight static adaptDimension(value: number): number {let deviceDisplay: display.Display GlobalContext.getContext().getObject(display) as display.Display;le…

int的最大值加1会变成int的最小值

一、概要 int是4个字节&#xff0c;总共是32个bit位&#xff0c;所以总共能表示2^32个数 int的最大值是2^31-1&#xff0c;也就是2147483647&#xff0c;大约21亿多 减的那个1表示自然数0的位置 int的最小值是-2^31&#xff0c;也就是-2147483648&#xff0c;大约负的21亿多…

[网鼎杯 2020 朱雀组]Nmap1

打开题目 在源代码中看到了提示 先随便输入127.0.0.1 那我们试试输入 127.0.0.1 | ls 可以看到 | 被转义符号\所转义 那我们输入 127.0.0.1 /| ls 得到三条反斜线 我们猜测&#xff0c;我们输入的东西是被escapeshellarg和escapeshellcmd处理过后的结果 我们输入的东西必须…

银行监管报送系统介绍(十六):外汇数据报送(BOP,ACC,FAL,JSH,CWD)

2023年5月初&#xff0c;外管局发布了《通过银行进行国际收支统计申报业务指引&#xff08;2023年版&#xff09;》&#xff0c;该报送指引主要针对的是外管局的国际收支统计&#xff08;即BOP&#xff09;模块的报送。 附件 1 通过银行进行国际收支统计申报业务指引 &#x…

基于PHP后台微信网上购物商城小程序系统设计与实现(安装部署+源码+文档)

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

ArcGIS操作(四)

任务&#xff1a; 根据江苏省夜间灯光影像完成数据处理与分析查阅统计年鉴数据以提取建成区空间分布位置完成建成区重心转移轨迹 步骤&#xff1a; 这里选取江苏省2000年、2004年、2008年夜光数据进行分析 加载影像 掩膜提取 投影 栅格转面 融合 栅格转面数据时分冗余&…

Echarts实现高亮某一个点

背景 接口会返回所有点的数据&#xff0c;以及最优点的数据。产品要求在绘制图形后&#xff0c;高亮最优点&#xff0c;添加一个红色的样式&#xff0c;如图。点击select选择器时&#xff0c;可选择不同指标和花费对应的关系。 以下介绍实现思路 1、自定义配置选择器的数据源…