Spring【声明式事务】
事务简介
- 把一组业务当成一个业务来做;要么都成功,要么都失败!
- 事务在项目开发中,十分重要,涉及到数据一致性的问题,需要十分注意!
- 确保完整性和一致性!
事务的ACID原则:
- 原子性
- 一致性
- 隔离性
- 多个业务在操作临界资源的时候,需要防止数据损坏。
- 持久性
案例:
先整合spring和mybatis
0、前置用户User类-通过注解帮我们生成有参和无参构造
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @Data 帮助生成toString、get和set等方法* @AllArgsConstructor 有参构造* @NoArgsConstructor 无参构造*/@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private int id;private String name;private String pwd;@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", pwd='" + pwd + '\'' +'}';}
}
1、我们定义一个接口类 UserMapper,它抽象了我们对数据库的操作。
public interface UserMapper {public List<User> selectUser();public int addUser(User user);public int deleteUserById(int id);
}
2、配置UserMapper.xml,绑定接口中的方法,并实现SQL的实现
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//OTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.mapper.UserMapper"><select id="selectUser" resultType="user">select * from mybatis.user;</select><insert id="addUser" parameterType="user">insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd});</insert><delete id="deleteUserById" parameterType="int">delete from mybatis.user where id = #{id};</delete>
</mapper>
3、写一个接口的实现类UserMapperImpl,对接口的功能进行实现:
import com.study.pojo.User;
import org.mybatis.spring.support.SqlSessionDaoSupport;import java.util.List;public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{@Overridepublic List<User> selectUser() {UserMapper mapper = getSqlSession().getMapper(UserMapper.class);return mapper.selectUser();}@Overridepublic int addUser(User user) {return getSqlSession().getMapper(UserMapper.class).addUser(user);}@Overridepublic int deleteUserById(int id) {return getSqlSession().getMapper(UserMapper.class).deleteUserById(id);}
}
4、我们在spring的配置文件applicationContext.xml中注册这个实现类的bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><import resource="spring-dao.xml"/><bean id="userMapper" class="com.study.mapper.UserMapperImpl"><property name="sqlSessionFactory" ref="sqlSessionFactory"/></bean>
</beans>
5、测试
import com.study.mapper.UserMapper;
import com.study.pojo.User;
import com.sun.org.apache.bcel.internal.util.ClassPath;
import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.List;public class MyTest {static ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");static UserMapper mapper = context.getBean("userMapper", UserMapper.class);public static void main(String[] args) {delUser(3);selectAll();System.out.println("============");addUser(new User(4,"李大喜","112233"));selectAll();}public static void selectAll(){List<User> list = mapper.selectUser();for (User user : list) {System.out.println(user);}}public static int delUser(int id){return mapper.deleteUserById(id);}public static int addUser(User user){return mapper.addUser(user);}
}
事务:
比如我们在selectAll()方法中增加一个用户并将新用户删除,而且我们将删除用户的SQL语句故意写错,这样执行的时候我们就是发现,我们的这个selectAll方法并没有体现出事务的特点,我们说事务应该是统一完成或者统一失败的,但是我们的这个方法结果却是添加了新用户但是并没有删除成功(因为我们的删除SQL是错误的),所以,我们要想一种办法来实现事务:
spring中事务的实现
spring 中事务的实现有两种方式:
- 声明式事务(通过AOP实现,不需要修改原业务代码)
- 编程式事务(通过try-catch,需要修改原业务代码)
我们更多的不去直接修改原本的业务代码,而是使用声明式事务
事务的实现
一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。而不是给 MyBatis 创建一个新的专用事务管理器,MyBatis-Spring 借助了 Spring DataSourceTransactionManager 来实现事务管理。
一旦配置好了 Spring 的事务管理器,你就可以在 Spring 中按你平时的方式来配置事务。并且支持 @Transactional 注解和 AOP 风格的配置。在事务处理期间,一个单独的 SqlSession 对象将会被创建和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。
事务配置好了以后,MyBatis-Spring 将会透明地管理事务。这样在你的 DAO 类中就不需要额外的代码了。
标准配置
要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象,也就是注册一个bean。
在我们的spring配置文件(可以在applicationContext.xml中区配置,也可以在我们数据源bean-dataSource所在的配置文件中配置,这里我们直接在spring-dao.xml中操作,因为我们的数据源bean在这个配置文件中,我们将所有与数据库操作相关的代码都放到这个配置文件中去便于后期查找和维护),因此这样我们中注册这样一个bean:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><constructor-arg ref="dataSource" />
</bean>
我们可以看到,其中需要指定引用-也就是我的数据源(数据库),这里我们是通过构造器注入的事务管理器对象,我们也可以通过属性来注入:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean>
交由容器管理事务
注册完成事务管理器后,我们需要交由容器来管理事务:
我们在spring含有sqlSessionFactory的配置文件中添加以下配置代码:
1、配置事务通知advice
1.1、导入 tx 约束文件
<?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:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd">
1.2、设置事务属性
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="selectUser" propagation="REQUIRED"/><tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice>
2、配置事务切入
2.1、导入切入约束
<?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: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/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd">
2.2、设置切入点
我们设置切入点的作用范围为com.study.mapper包下所有类的所有方法。
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="selectUser" propagation="REQUIRED"/><tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice><!--对应tx标签内的id-->
<aop:config><aop:pointcut id="txPointCut" expression="execution(* com.study.mapper.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/></aop:config>
测试
我们继续测试selectUser方法,我们故意将其中嵌套的delUser方法的SQL雨具写错,观察先执行的addUser方法是否执行,因为它是在delUser方法执行前的,他们是一整个事务,如果配置成功应该是一起成功或失败:
我们发现,配置事务之后,我们的selectUser方法内部的方法也都是一起成功或失败的,事务功能实现!
总结
主要就配置三部分:
- 配置事务管理器
- 配置事务通知
- 配置切入点
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><constructor-arg ref="dataSource" /><property name="dataSource" ref="dataSource"/></bean><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="selectUser" propagation="REQUIRED"/><tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice><aop:config><aop:pointcut id="txPointCut" expression="execution(* com.study.mapper.*.*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/></aop:config>
事务在项目中十分重要!
相关文章:
Spring【声明式事务】
事务简介 把一组业务当成一个业务来做;要么都成功,要么都失败!事务在项目开发中,十分重要,涉及到数据一致性的问题,需要十分注意!确保完整性和一致性! 事务的ACID原则:…...
【雕爷学编程】MicroPython动手做(17)——掌控板之触摸引脚2
知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…...
pytorch 中 view 和reshape的区别
在 PyTorch(一个流行的深度学习框架)中, reshape 和 view 都是用于改变张量(tensor)形状的方法,但它们在实现方式和使用上有一些区别。下面是它们之间的主要区别: 实现方式: reshap…...
认识数组指针
文章目录 数组指针的定义数组指针的应用 数组指针的定义 类比 整形数组——存放整形的数组 指针数组——存放指针的数组 整形指针——存放整形地址的指针 数组指针——存放数组地址的指针 深度理解 在之前我们知道:数组名表示首元素地址,但是有…...
SSM面试题-Spring容器的启动流程
解答: 1. BeanDefinitionReader读取配置文件(xml yml properties),创建BeanDefinition(存储bean的定义信息) 2. 配置文件读取成功后,将相应的配置转换成 BeanDefinition 的对象实例保存在DefaultListableBeanFactory#beanDefinitionMap 中 3. 根据配置的 BeanFacto…...
Vue 3:玩一下web前端技术(八)
前言 本章内容为VUE基础与相关技术讨论。 上一篇文章地址: Vue 3:玩一下web前端技术(七)_Lion King的博客-CSDN博客 下一篇文章地址: (暂无) 一、基础 官方文档:创建一个 Vue…...
AI绘画Stable Diffusion原理之Autoencoder-Latent
前言 传送门: stable diffusion:Git|论文 stable-diffusion-webui:Git Google Colab Notebook:Git kaggle Notebook:Git 今年AIGC实在是太火了,让人大呼许多职业即将消失,比如既能帮…...
C++核心知识点总结
学习一门新的程序设计语言得到最好方法就是练习编写程序! C基础 变量和基本类型 基本内置类型 定义解释 算术类型 整型:包括字符和布尔类型,bool、char、wchar_t、char16_t、char32_t、short、int、long、long long、 浮点型:…...
echart折线图,调节折线点和y轴的间距(亲测可用)
options代码: options {tooltip: {trigger: axis, //坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。},xAxis: {type: category,//类目轴,适用于离散的类目数据,为该类型时必须通过 data 设置类目数据。…...
Power BI-云端报表定时刷新--ODBC、MySQL、Oracle等其他本地数据源的刷新(二)
ODBC数据源 一些小众的数据源无法直接连接,需要通过微软系统自带的应用“ODBC数据源”连接。 1.首次使用应安装对应数据库的ODBC驱动程序,Mysql的ODBC驱动需要手动安装 2.在web服务中进行数据源的配置 Mysql数据源 1.Powerbi与Gateway第一次连SQL…...
redis 淘汰策略和持久化
文章目录 一、淘汰策略1.1 背景1.2 淘汰策略 二、持久化2.1 AOF日志2.1.1 AOF配置2.1.2 AOF策略2.1.3 AOF缺点2.1.4 AOF Rewrite2.1.5 AOF Rewrite配置2.1.6 AOF Rewrite缺点2.1.7 fork进程时的写时复制2.1.8 大key对持久化的影响 2.2 RDB快照2.2.1 RDB配置2.2.2 RDB缺点 2.3 混…...
Redis学习路线(6)—— Redis的分布式锁
一、分布式锁的模型 (一)悲观锁: 认为线程安全问题一定会发生,因此在操作数据之前先获取锁,确保线程串行执行。例如Synchronized、Lock都属于悲观锁。 优点: 简单粗暴缺点: 性能略低 &#x…...
一、创建自己的docker python容器环境;支持新增python包并更新容器;离线打包、加载image
1、创建自己的docker python容器环境 参考:https://blog.csdn.net/weixin_42357472/article/details/118991485 首先写Dockfile,注意不要有txt等后缀 Dockfile # 使用 Python 3.9 镜像作为基础 FROM python:3.9# 设置工作目录 WORKDIR /app# 复制当前…...
【Git】git企业开发命令整理,以及注意点
1.git企业开发过程 业务的分支大概有以下几个: master:代码随时可能上线 develop:代码最新 feature/xxx:实际业务开发分支 release/xxx:预发布分支 fix:修复bug分支 过程大概是这样的: 首…...
使用Django自带的后台管理系统进行数据库管理的实例
Django自带的后台管理系统主要用来对数据库进行操作和管理。它是Django框架的一个强大功能,可以让你快速创建一个管理界面,用于管理你的应用程序的数据模型。 使用Django后台管理系统,你可以轻松地进行以下操作: 数据库管理&…...
leetcode解题思路分析(一百四十五)1254 - 1266 题
统计封闭岛屿的数目 二维矩阵 grid 由 0 (土地)和 1 (水)组成。岛是由最大的4个方向连通的 0 组成的群,封闭岛是一个 完全 由1包围(左、上、右、下)的岛。请返回 封闭岛屿 的数目。 BFS或者DFS…...
使用 GORM 连接数据库并实现增删改查操作
步骤 1:安装 GORM 首先,我们需要安装 GORM 包。在终端中运行以下命令: shell go get -u gorm.io/gorm 步骤 2:导入所需的包 在 Go 代码的开头导入以下包: import ("gorm.io/driver/mysql" // 如果你使用…...
kafka集群搭建(Linux环境)
zookeeper搭建,可以搭建集群,也可以单机(本地学习,没必要搭建zookeeper集群,单机完全够用了,主要学习的是kafka) 1. 首先官网下载zookeeper:Apache ZooKeeper 2. 下载好之后上传到…...
树莓派本地快速搭建web服务器,并发布公网访问
文章目录 树莓派本地快速搭建web服务器,并发布公网访问 树莓派本地快速搭建web服务器,并发布公网访问 随着科技的发展,电子工业也在不断进步,我们身边的电子设备也在朝着小型化和多功能化演进,以往体积庞大的电脑也在…...
集合中的数据结构
栈 先进后出入口跟出口在同一侧 队列 先进先出入口跟出口在不同的一层 数组 查询快、增删慢查询快是因为数组的地址是连续的,我们通过数组的首地址就可以找到数组,之后通过数组的下标就可以访问数组的每一个元素。增删慢是因为数组的长度是固定的&…...
Kali Linux 2024.2 环境下,用 Python 脚本复现一次 DDoS 攻击实验(仅供学习防御)
Kali Linux 2024.2环境下Python脚本模拟DDoS攻击实验与防御研究 在网络安全领域,理解攻击原理是构建有效防御体系的基础。本文将带您在Kali Linux 2024.2环境中,通过Python脚本模拟一次DDoS攻击实验,重点分析攻击流量特征,并探讨如…...
终极指南:如何用amdgpu_top实时监控AMD显卡性能
终极指南:如何用amdgpu_top实时监控AMD显卡性能 【免费下载链接】amdgpu_top Tool to display AMDGPU usage 项目地址: https://gitcode.com/gh_mirrors/am/amdgpu_top 还在为AMD显卡性能监控而烦恼吗?想要像NVIDIA用户使用nvidia-smi那样轻松掌握…...
DBSwitch迁移踩坑记:当PostgreSQL的TRUNCATE语法遇上openGauss,我这样改源码
DBSwitch迁移实战:从PostgreSQL到openGauss的TRUNCATE语法改造之旅 在异构数据库迁移领域,DBSwitch作为一款高效的工具,能够实现不同数据库之间的数据流转。然而,当我们将目光投向PostgreSQL与openGauss这两种看似同源却存在微妙差…...
基于随机森林的加州房价二分类实验
一、加州房价数据集介绍 本实验使用模拟加州房价数据集完成随机森林二分类任务,通过构建房屋特征与房价等级的映射关系,实现房价高低二分类预测,掌握随机森林集成学习算法、模型评估、特征重要性分析与参数调优方法。 数据集简介 数据集名称&…...
为什么82%的保险AI Agent项目卡在POC阶段?一线技术总监首度公开6个致命设计盲区
更多请点击: https://codechina.net 第一章:为什么82%的保险AI Agent项目卡在POC阶段? 保险行业正加速拥抱AI Agent技术,但据2024年《亚太保险科技落地白皮书》统计,82%的AI Agent项目在概念验证(POC&…...
告别手动转换:docx2tex如何让Word到LaTeX的转换变得简单高效
告别手动转换:docx2tex如何让Word到LaTeX的转换变得简单高效 【免费下载链接】docx2tex Converts Microsoft Word docx to LaTeX 项目地址: https://gitcode.com/gh_mirrors/do/docx2tex 还在为Word文档转换为LaTeX格式而烦恼吗?每次手动调整格式…...
毕业答辩PPT救星:百考通AI如何用30分钟搞定高质量学术汇报
又到一年毕业季,相信不少同学在论文定稿后,突然发现自己卡在了最后一关——毕业答辩PPT的制作上。这份看似简单的PPT,却是评审老师对你研究成果形成第一印象的关键载体,甚至直接影响答辩的通过率。 然而现实是,许多同…...
机器学习实战地形图:从问题定义到模型监控的端到端闭环
1. 项目概述:这不是一本“速成手册”,而是一张机器学习领域的实操地形图 “Machine Learning A-Z Briefly Explained”——光看标题,很多人第一反应是“又一本入门书?”、“是不是那种翻两页就堆满公式、第三章就开始推导梯度下降…...
如何3分钟上手B站视频下载神器:BilibiliDown跨平台下载完全指南
如何3分钟上手B站视频下载神器:BilibiliDown跨平台下载完全指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_…...
学网安压根不卡学历,在校生自学这样走少绕好几年弯路
学网安压根不卡学历,在校生自学这样走少绕好几年弯路 前言 “网络安全只有计算机高材生才能学?” “没有名校背景,根本进不了这个行业?” “普通专科生、本科生、非科班出身想要自学网络安全,难度太大了吧…...
