当前位置: 首页 > news >正文

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方法内部的方法也都是一起成功或失败的,事务功能实现!

总结

主要就配置三部分:

  1. 配置事务管理器
  2. 配置事务通知
  3. 配置切入点
<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【声明式事务】

事务简介 把一组业务当成一个业务来做&#xff1b;要么都成功&#xff0c;要么都失败&#xff01;事务在项目开发中&#xff0c;十分重要&#xff0c;涉及到数据一致性的问题&#xff0c;需要十分注意&#xff01;确保完整性和一致性&#xff01; 事务的ACID原则&#xff1a;…...

【雕爷学编程】MicroPython动手做(17)——掌控板之触摸引脚2

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…...

pytorch 中 view 和reshape的区别

在 PyTorch&#xff08;一个流行的深度学习框架&#xff09;中&#xff0c; reshape 和 view 都是用于改变张量&#xff08;tensor&#xff09;形状的方法&#xff0c;但它们在实现方式和使用上有一些区别。下面是它们之间的主要区别&#xff1a; 实现方式&#xff1a; reshap…...

认识数组指针

文章目录 数组指针的定义数组指针的应用 数组指针的定义 类比 整形数组——存放整形的数组 指针数组——存放指针的数组 整形指针——存放整形地址的指针 数组指针——存放数组地址的指针 深度理解 在之前我们知道&#xff1a;数组名表示首元素地址&#xff0c;但是有&#xf…...

SSM面试题-Spring容器的启动流程

解答: 1. BeanDefinitionReader读取配置文件(xml yml properties),创建BeanDefinition(存储bean的定义信息) 2. 配置文件读取成功后&#xff0c;将相应的配置转换成 BeanDefinition 的对象实例保存在DefaultListableBeanFactory#beanDefinitionMap 中 3. 根据配置的 BeanFacto…...

Vue 3:玩一下web前端技术(八)

前言 本章内容为VUE基础与相关技术讨论。 上一篇文章地址&#xff1a; Vue 3&#xff1a;玩一下web前端技术&#xff08;七&#xff09;_Lion King的博客-CSDN博客 下一篇文章地址&#xff1a; &#xff08;暂无&#xff09; 一、基础 官方文档&#xff1a;创建一个 Vue…...

AI绘画Stable Diffusion原理之Autoencoder-Latent

前言 传送门&#xff1a; stable diffusion&#xff1a;Git&#xff5c;论文 stable-diffusion-webui&#xff1a;Git Google Colab Notebook&#xff1a;Git kaggle Notebook&#xff1a;Git 今年AIGC实在是太火了&#xff0c;让人大呼许多职业即将消失&#xff0c;比如既能帮…...

C++核心知识点总结

学习一门新的程序设计语言得到最好方法就是练习编写程序&#xff01; C基础 变量和基本类型 基本内置类型 定义解释 算术类型 整型&#xff1a;包括字符和布尔类型&#xff0c;bool、char、wchar_t、char16_t、char32_t、short、int、long、long long、 浮点型&#xff1a;…...

echart折线图,调节折线点和y轴的间距(亲测可用)

options代码&#xff1a; options {tooltip: {trigger: axis, //坐标轴触发&#xff0c;主要在柱状图&#xff0c;折线图等会使用类目轴的图表中使用。},xAxis: {type: category,//类目轴&#xff0c;适用于离散的类目数据&#xff0c;为该类型时必须通过 data 设置类目数据。…...

Power BI-云端报表定时刷新--ODBC、MySQL、Oracle等其他本地数据源的刷新(二)

ODBC数据源 一些小众的数据源无法直接连接&#xff0c;需要通过微软系统自带的应用“ODBC数据源”连接。 1.首次使用应安装对应数据库的ODBC驱动程序&#xff0c;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的分布式锁

一、分布式锁的模型 &#xff08;一&#xff09;悲观锁&#xff1a; 认为线程安全问题一定会发生&#xff0c;因此在操作数据之前先获取锁&#xff0c;确保线程串行执行。例如Synchronized、Lock都属于悲观锁。 优点&#xff1a; 简单粗暴缺点&#xff1a; 性能略低 &#x…...

一、创建自己的docker python容器环境;支持新增python包并更新容器;离线打包、加载image

1、创建自己的docker python容器环境 参考&#xff1a;https://blog.csdn.net/weixin_42357472/article/details/118991485 首先写Dockfile&#xff0c;注意不要有txt等后缀 Dockfile # 使用 Python 3.9 镜像作为基础 FROM python:3.9# 设置工作目录 WORKDIR /app# 复制当前…...

【Git】git企业开发命令整理,以及注意点

1.git企业开发过程 业务的分支大概有以下几个&#xff1a; master&#xff1a;代码随时可能上线 develop&#xff1a;代码最新 feature/xxx&#xff1a;实际业务开发分支 release/xxx&#xff1a;预发布分支 fix&#xff1a;修复bug分支 过程大概是这样的&#xff1a; 首…...

使用Django自带的后台管理系统进行数据库管理的实例

Django自带的后台管理系统主要用来对数据库进行操作和管理。它是Django框架的一个强大功能&#xff0c;可以让你快速创建一个管理界面&#xff0c;用于管理你的应用程序的数据模型。 使用Django后台管理系统&#xff0c;你可以轻松地进行以下操作&#xff1a; 数据库管理&…...

leetcode解题思路分析(一百四十五)1254 - 1266 题

统计封闭岛屿的数目 二维矩阵 grid 由 0 &#xff08;土地&#xff09;和 1 &#xff08;水&#xff09;组成。岛是由最大的4个方向连通的 0 组成的群&#xff0c;封闭岛是一个 完全 由1包围&#xff08;左、上、右、下&#xff09;的岛。请返回 封闭岛屿 的数目。 BFS或者DFS…...

使用 GORM 连接数据库并实现增删改查操作

步骤 1&#xff1a;安装 GORM 首先&#xff0c;我们需要安装 GORM 包。在终端中运行以下命令&#xff1a; shell go get -u gorm.io/gorm 步骤 2&#xff1a;导入所需的包 在 Go 代码的开头导入以下包&#xff1a; import ("gorm.io/driver/mysql" // 如果你使用…...

kafka集群搭建(Linux环境)

zookeeper搭建&#xff0c;可以搭建集群&#xff0c;也可以单机&#xff08;本地学习&#xff0c;没必要搭建zookeeper集群&#xff0c;单机完全够用了&#xff0c;主要学习的是kafka&#xff09; 1. 首先官网下载zookeeper&#xff1a;Apache ZooKeeper 2. 下载好之后上传到…...

树莓派本地快速搭建web服务器,并发布公网访问

文章目录 树莓派本地快速搭建web服务器&#xff0c;并发布公网访问 树莓派本地快速搭建web服务器&#xff0c;并发布公网访问 随着科技的发展&#xff0c;电子工业也在不断进步&#xff0c;我们身边的电子设备也在朝着小型化和多功能化演进&#xff0c;以往体积庞大的电脑也在…...

集合中的数据结构

栈 先进后出入口跟出口在同一侧 队列 先进先出入口跟出口在不同的一层 数组 查询快、增删慢查询快是因为数组的地址是连续的&#xff0c;我们通过数组的首地址就可以找到数组&#xff0c;之后通过数组的下标就可以访问数组的每一个元素。增删慢是因为数组的长度是固定的&…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...