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

SpringBoot 事务

事务是一组操作的集合, 是一个不可分割的操作.会把所有的操作作为一个整体, 一起向数据库提交或者是撤销操作请求. 所以这组操作要么同时成功, 要么同时失败.


为什么需要事务?

我们在进行程序开发时, 也会有事务的需求.

比如转账操作:

第一步:A 账户 -100 元.

第二步:B 账户 +100 元.

如果没有事务,第一步执行成功了, 第二步执行失败了, 那么A 账户的100 元就平白无故消失了. 如果使用事务就可以解决这个问题, 让这一组操作要么一起成功, 要么一起失败.

比如秒杀系统,

第一步: 下单成功

第二步: 扣减库存

下单成功后, 库存也需要同步减少. 如果下单成功, 库存扣减失败, 那么就会造成下单超出的情况. 所以就需要把这两步操作放在同一个事务中. 要么一起成功, 要么一起失败.

理解事务概念为主, 实际企业开发时, 并不是简单的通过事务来处理.

事务的操作

事务的操作主要有三步:

  1. 开启事start transaction/ begin (一组操作前开启事务)
  2. 提交事务: commit (这组操作全部成功, 提交事务)
  3. 回滚事务: rollback (这组操作中间任何一个操作出现异常, 回滚事务)
-- 开启事务
start transaction;
-- 提交事务
commit;
-- 回滚事务
rollback;

Spring中事务的实现

Spring 中的事务操作分为两类:

  1. 编程式事务(手动写代码操作事务).
  2. 声明式事务(利用注解自动开启和提交事务).
-- 创建数据库
DROP DATABASE IF EXISTS trans_test;
CREATE DATABASE trans_test DEFAULT CHARACTER SET utf8mb4;
-- 用户表
DROP TABLE IF EXISTS user_info;
CREATE TABLE user_info (
`id` INT NOT NULL AUTO_INCREMENT,
`user_name` VARCHAR (128) NOT NULL,
`password` VARCHAR (128) NOT NULL,
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now() ON UPDATE now(),
PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARACTER
SET = utf8mb4 COMMENT = '用户表';
-- 操作日志表
DROP TABLE IF EXISTS log_info;
CREATE TABLE log_info (
`id` INT PRIMARY KEY auto_increment,
`user_name` VARCHAR ( 128 ) NOT NULL,
`op` VARCHAR ( 256 ) NOT NULL,
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now() ON UPDATE now()
) DEFAULT charset 'utf8mb4';

配置文件

# 数据库连接配置
spring:datasource:url: jdbc:mysql://localhost:3306/trans_test?characterEncoding=utf8&useSSL=falseusername: rootpassword: 123driver-class-name: com.mysql.cj.jdbc.Driver# 设置动态代理的方式 true jdk代理, false cglib代理aop:proxy-target-class: true
mybatis:configuration:map-underscore-to-camel-case: true #配置驼峰自动转换
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印sql语句mapper-locations: classpath:mapper/**Mapper.xml
# 设置日志文件的文件名
logging:file:name: logger/spring-book.log

实体类

@Data
public class LogInfo {private Integer id;private String userName;private String op;private Date createTime;private Date updateTime;
}@Data
public class UserInfo {private Integer id;private String userName;private String password;private Date createTime;private Date updateTime;
}

mapper

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserInfoMapper {@Insert("insert into user_info(`user_name`,`password`)values(#{name},#{password})")Integer insert(String name,String password);
}import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface LogInfoMapper {@Insert("insert into log_info(`user_name`,`op`)values(#{name},#{op})")Integer insertLog(String name,String op);
}

service

@Slf4j
@Service
public class UserService {@Autowiredprivate UserInfoMapper userInfoMapper;public void registryUser(String name,String password){
//插入用户信息userInfoMapper.insert(name,password);}
}@Slf4j
@Service
public class LogService {@Autowiredprivate LogInfoMapper logInfoMapper;public void insertLog(String name,String op){//记录用户操作logInfoMapper.insertLog(name,"用户注册");}
}

controller

@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@RequestMapping("/registry")public String registry(String name,String password){//用户注册userService.registryUser(name,password);return "注册成功";}
}

Spring编程式事务

Spring 手动操作事务和上面 MySQL 操作事务类似, 有 3 个重要操作步骤:

• 开启事务(获取事务)

• 提交事务

• 回滚事务

SpringBoot 内置了两个对象:

  1. DataSourceTransactionManager 事务管理器. 用来获取事务(开启事务), 提交或回滚事务的
  2. TransactionDefinition 是事务的属性, 在获取事务的时候需要将TransactionDefinition 传递进去从而获得一个事务 TransactionStatus

事务交提

@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;@Autowiredprivate TransactionDefinition transactionDefinition;@Autowiredprivate UserService userService;@RequestMapping("/registry")public String registry(String name,String password){TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);//用户注册userService.registryUser(name,password);// 提交事务dataSourceTransactionManager.commit(transaction);//回滚事务//dataSourceTransactionManager.rollback(transactionStatus);return "注册成功";}
}

http://localhost:8080/user/registry?name=user1&password=123123


事务回滚

@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;@Autowiredprivate TransactionDefinition transactionDefinition;@Autowiredprivate UserService userService;@RequestMapping("/registry")public String registry(String name,String password){TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);//用户注册userService.registryUser(name,password);//回滚事务dataSourceTransactionManager.rollback(transactionStatus);return "注册成功";}
}

http://localhost:8080/user/registry?name=user2&password=123123

虽然返回结果时注册成功,但是数据库中并没有插入数据。

Spring声明式事务@Transactional

声明式事务的实现很简单, 只需要在需要事务的方法上添加 @Transactional 注解就可以实现了.无需手动开启事务和提交事务, 进入方法时自动开启事务, 方法执行完会自动提交事务, 如果中途发生了没有处理的异常会自动回滚事务.

@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@Transactional@RequestMapping("/registry")public String registry(String name,String password){userService.registryUser(name,password);return "注册成功";}
}

http://localhost:8080/user/registry?name=user2&password=123123

数据库中插入了数据。


使程序出现异常

@RequestMapping("/user")
@RestController
public class UserController {@Autowiredprivate UserService userService;@Transactional@RequestMapping("/registry")public String registry(String name,String password){userService.registryUser(name,password);int a = 10 / 0;return "注册成功";}
}

事务会进行回滚,所以数据库中没有新插入的数据。

我们一般会在业务逻辑层当中来控制事务, 因为在业务逻辑层当中, 一个业务功能可能会包含多个数据访问的操作. 在业务逻辑层来控制事务, 我们就可以将多个数据访问操作控制在一个事务范围内.

Transactional作用

@Transactional 可以用来修饰方法或类:

• 修饰方法时: 只有修饰public 方法时才生效(修饰其他方法时不会报错, 也不生效)[推荐]

• 修饰类时: 对@Transactional 修饰的类中所有的 public 方法都生效.

方法/类被 @Transactional 注解修饰时, 在目标方法执行开始之前, 会自动开启事务, 方法执行结之后, 自动提交事务.如果在方法执行过程中, 出现异常, 且异常未被捕获, 就进行事务回滚操作.如果异常被程序捕获, 方法就被认为是成功执行, 依然会提交事务.

@Transactional
@RequestMapping("/registry")
public String registry(String name,String password){//用户注册userService.registryUser(name,password);log.info("用户数据插入成功");//对异常进行捕获try {//强制程序抛出异常int a = 10/0;}catch (Exception e){e.printStackTrace();}return "注册成功";
}

运行程序, 发现虽然程序出错了, 但是由于异常被捕获了, 所以事务依然得到了提交.

如果需要事务进行回滚, 有以下两种方式:

  1. 重新抛出异常
@Transactional
@RequestMapping("/registry")
public String registry(String name,String password){//用户注册userService.registryUser(name,password);log.info("用户数据插入成功");//对异常进行捕获try {//强制程序抛出异常int a = 10/0;}catch (Exception e){//将异常重新抛出去throw e;}return "注册成功";
}
  1. 手动回滚事务
// 使用 TransactionAspectSupport.currentTransactionStatus() 得到当前的事务, 并
// 使用 setRollbackOnly 设置setRollbackOnly
@Transactional
@RequestMapping("/registry")
public String registry(String name,String password){//用户注册userService.registryUser(name,password);log.info("用户数据插入成功");//对异常进行捕获try {//强制程序抛出异常int a = 10/0;}catch (Exception e){// 手动回滚事务TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return "注册成功";
}

Transactional详解

通过上面的代码, 我们学习了@Transactional 的基本使用. 接下来我们学习@Transactional注解的使用细节.
我们主要学习@Transactional 注解当中的三个常见属性:

  1. rollbackFor: 异常回滚属性. 指定能够触发事务回滚的异常类型. 可以指定多个异常类型
  2. Isolation: 事务的隔离级别. 默认值为Isolation.DEFAULT
  3. propagation: 事务的传播机制. 默认值为 Propagation.REQUIRED

rollbackFor

@Transactional 默认只在遇到运行时异常和Error时才会回滚, 非运行时异常不回滚. 即Exception的子类中, 除了RuntimeException及其子类.

修改一下代码

@Transactional
@RequestMapping("/r2")
public String r2(String name,String password) throws IOException {//用户注册userService.registryUser(name,password);log.info("用户数据插入成功");if (true){throw new IOException();}return "r2";
}

发现虽然程序抛出了异常, 但是事务依然进行了提交.

如果我们需要所有异常都回滚, 需要来配置@Transactional 注解当中的rollbackFor 属性, 通过rollbackFor 这个属性指定出现何种异常类型时事务进行回滚.

@Transactional(rollbackFor = Exception.class)
@RequestMapping("/r2")
public String r2(String name,String password) throws IOException {//用户注册userService.registryUser(name,password);log.info("用户数据插入成功");if (true){throw new IOException();}return "r2";
}

数据回滚了。

在Spring的事务管理中,默认只在遇到运行时异常RuntimeException和Error时才会回滚.

如果需要回滚指定类型的异常, 可以通过rollbackFor属性来指定.

事务隔离级别

MySQL事务隔离级别

  1. 读未提交(READ UNCOMMITTED): 读未提交, 也叫未提交读. 该隔离级别的事务可以看到其他事务中未提交的数据.(因为其他事务未提交的数据可能会发生回滚, 但是该隔离级别却可以读到, 我们把该级别读到的数
    据称之为脏数据, 这个问题称之为脏读.)
  2. 读提交(READ COMMITTED): 读已提交, 也叫提交读. 该隔离级别的事务能读取到已经提交事务的数据,(该隔离级别不会有脏读的问题.但由于在事务的执行中可以读取到其他事务提交的结果, 所以在不同时间的相同 SQL 查询可能会得到不同的结果, 这种现象叫做不可重复读)
  3. 可重复读(REPEATABLE READ): 事务不会读到其他事务对已有数据的修改, 即使其他事务已提交. 也就可以确保同一事务多次查询的结果一致, 但是其他事务新插入的数据, 是可以感知到的. 这也就引发了幻读问题. 可重复读, 是 MySQL 的默认事务隔离级别.(比如此级别的事务正在执行时, 另一个事务成功的插入了某条数据, 但因为它每次查询的结果都是一样的, 所以会导致查询不到这条数据, 自己重复插入时又失败(因为唯一约束的原因). 明明在事务中查询不到这条信息,但自己就是插入不进去, 这个现象叫幻读.)
  4. 串行化(SERIALIZABLE): 序列化, 事务最高隔离级别. 它会强制事务排序, 使之不会发生冲突, 从而解决了脏读, 不可重复读和幻读问题, 但因为执行效率低, 所以真正使用的场景并不多.

Spring事务隔离级别

Spring 中事务隔离级别有5 种:

  1. Isolation.DEFAULT : 以连接的数据库的事务隔离级别为主.
  2. Isolation.READ_UNCOMMITTED : 读未提交, 对应SQL标准中 READ UNCOMMITTED
  3. Isolation.READ_COMMITTED : 读已提交,对应SQL标准中 READ COMMITTED
  4. Isolation.REPEATABLE_READ : 可重复读, 对应SQL标准中 REPEATABLE READ
  5. Isolation.SERIALIZABLE : 串行化, 对应SQL标准中 SERIALIZABLE
public enum Isolation {DEFAULT(-1),READ_UNCOMMITTED(1),READ_COMMITTED(2),REPEATABLE_READ(4),SERIALIZABLE(8);private final int value;private Isolation(int value) {this.value = value;}public int value() {return this.value;}
}

Spring 中事务隔离级别可以通过 @Transactional 中的 isolation 属性进行设置

@Transactional(isolation = Isolation.READ_COMMITTED)
@RequestMapping("/r3")
public String r3(String name,String password) throws IOException {//... 代码省略return "r3";
}

Spring事务传播机制

事务传播机制就是: 多个事务方法存在调用关系时, 事务是如何在这些方法间进行传播的.

比如有两个方法A, B都被@Transactional 修饰, A方法调用B方法,A方法运行时, 会开启一个事务. 当A调用B时, B方法本身也有事务, 此时B方法运行时, 是加入A的事务, 还是创建一个新的事务呢?

这个就涉及到了事务的传播机制.

事务隔离级别解决的是多个事务同时调用一个数据库的问题

而事务传播机制解决的是一个事务在多个节点(方法)中传递的问题

事务传播机制有哪些

@Transactional 注解支持事务传播机制的设置, 通过 propagation 属性来指定传播行为.
Spring 事务传播机制有以下 7 种:

  1. Propagation.REQUIRED : 默认的事务传播级别. 如果当前存在事务, 则加入该事务. 如果当前没有事务, 则创建一个新的事务.
  2. Propagation.SUPPORTS : 如果当前存在事务, 则加入该事务. 如果当前没有事务, 则以非事务的方式继续运行.
  3. Propagation.MANDATORY :强制性. 如果当前存在事务, 则加入该事务. 如果当前没有事务, 则抛出异常.
  4. Propagation.REQUIRES_NEW : 创建一个新的事务. 如果当前存在事务, 则把当前事务挂起. 也就是说不管外部方法是否开启事务, Propagation.REQUIRES_NEW 修饰的内部方法都会新开启自己的事务, 且开启的事务相互独立, 互不干扰.
  5. Propagation.NOT_SUPPORTED : 以非事务方式运行, 如果当前存在事务, 则把当前事务挂起(不用).
  6. Propagation.NEVER : 以非事务方式运行, 如果当前存在事务, 则抛出异常.
  7. Propagation.NESTED : 如果当前存在事务, 则创建一个事务作为当前事务的嵌套事务来运行.如果当前没有事务, 则该取值等价于 PROPAGATION_REQUIRED .
public enum Propagation {REQUIRED(0),SUPPORTS(1),MANDATORY(2),REQUIRES_NEW(3),NOT_SUPPORTED(4),NEVER(5),NESTED(6);private final int value;private Propagation(int value) {this.value = value;}public int value() {return this.value;}
}

  1. Spring中使用事务, 有两种方式: 编程式事务(手动操作)和声明式事务. 其中声明式事务使用较多,在方法上添加 @Transactional 就可以实现了
  2. 通过 @Transactional(isolation = Isolation.SERIALIZABLE) 设置事务的隔离级别. Spring 中的事务隔离级别有 5 种
  3. 通过 @Transactional(propagation = Propagation.REQUIRED) 设置事务的传播机制, Spring 中的事务传播级别有 7 种, 重点关注 REQUIRED (默认值) 和 REQUIRES_NEW

相关文章:

SpringBoot 事务

事务是一组操作的集合, 是一个不可分割的操作.会把所有的操作作为一个整体, 一起向数据库提交或者是撤销操作请求. 所以这组操作要么同时成功, 要么同时失败. 为什么需要事务? 我们在进行程序开发时, 也会有事务的需求. 比如转账操作: 第一步:A 账户 -100 元. …...

我的JAVA-Web基础(1)

1.HTML 2.css CSS(层叠样式表)提供了多种选择器来定位HTML文档中的元素,以便可以应用样式。以下是三种常用的选择器简述: ID 选择器: ID选择器使用HTML元素的id属性来定位单个元素。每个页面中id应该是唯一的&#xf…...

【Leetcode 热题 100】207. 课程表

问题背景 你这个学期必须选修 n u m C o u r s e s numCourses numCourses 门课程,记为 0 0 0 到 n u m C o u r s e s − 1 numCourses - 1 numCourses−1。 在选修某些课程之前需要一些先修课程。 先修课程按数组 p r e r e q u i s i t e s prerequisites p…...

从CreateDialogIndirectParam起---我与大模型对话

前言: 对当前的大模型来说,一切皆程序,皆标准。只能按照推定的线路行走,就像机器人走进死胡同,不停的踏步也不回头。除非人为去干预它。其实我提出的这个问题前是因为我不清楚了解一部分WinAPI有着严格的检查机制和自毁…...

重温设计模式--建造者模式

文章目录 建造者模式(Builder Pattern)概述建造者模式UML图作用:建造者模式的结构产品(Product):抽象建造者(Builder):具体建造者(Concrete Builder&#xff…...

CSS(五):定位

目录 相对定位 绝对定位 固定定位 在 CSS 中,position 属性用于控制元素的定位方式,使我们可以精确地控制元素在页面上的位置。定位分为相对定位、绝对定位、和固定定位 相对定位 相对定位:position: relative; 相对定位意味着元素的位置…...

JSON 系列之2:JSON简单查询

本文为Oracle数据库JSON学习系列的第2篇,讲述如何对存储在数据库中的JSON文档进行简单的查询。 创建测试表,插入2条数据: DROP TABLE colortab PURGE;CREATE TABLE colortab (id NUMBER,color VARCHAR2(4000),CONSTRAINT ensure_json CH…...

SQL 简单查询

目录 一、投影查询 1、指定特定列查询 2、修改返回列名查询 3、计算值查询 二、选择查询 1、使用关系表达式 2、使用逻辑表达式 3、使用 BETWEEN关键字 4、使用 IN关键字 5、使用 LIKE关键字 6、使用 IS NULL/ NOT NULL关键字 7、符合条件查询 三、聚合函数查询 一…...

YOLOv9-0.1部分代码阅读笔记-metrics.py

metrics.py utils\metrics.py 目录 metrics.py 1.所需的库和模块 2.def fitness(x): 3.def smooth(y, f0.05): 4.def ap_per_class(tp, conf, pred_cls, target_cls, plotFalse, save_dir., names(), eps1e-16, prefix""): 5.def compute_ap(recall, prec…...

KaiOS 4.0 | DataCall and setupData implemention

相关文档 1、KaiOS 3.1 系统介绍 KaiOS 系统框架和应用结构(APP界面逻辑)文章浏览阅读842次,点赞17次,收藏5次。对于Java开发者而言,理解JS的逻辑调用是有点困难的。而KaiOS webapp开发又不同于现代的web开发,更像chrome浏览器内嵌模式。在这里梳理一下kaios平台web应用…...

nginx-rtmp服务器搭建

音视频服务器搭建 本文采用 nginx/1.18.0和nginx-rtmp-module模块源代码搭建RTMP流媒体服务器 流程 查看当前服务器的nginx版本下载nginx和nginx-rtmp-module源代码重新编译nginx,并进行相关配置(nginx.conf、防火墙等)客户端测试连接测试搭…...

[c++进阶(三)]单例模式及特殊类的设计

1.前言 在实际场景中,总会遇见一些特殊情况,比如设计一个类,只能在堆上开辟空间, 或者是设计一个类只能实例化一个对象。那么我们应该如何编写代码呢?本篇将会详细的介绍 本章重点: 本篇文章着重讲解如何设计一些特殊 的类,包括不能被拷贝,只能在栈/堆上…...

企业内训|高智能数据构建和多模态数据处理、Agent研发及AI测评技术内训-吉林省某汽车厂商

吉林省某汽车厂商为提升员工在AI大模型技术方面的知识和实践能力,举办本次为期8天的综合培训课程。本课程涵盖“高智能数据构建与智驾云多模态数据处理”、“AI Agent的研发”和“大模型测评”三大模块。通过系统梳理从非结构化数据的高效标注与融合,到L…...

009 Qt_显示类控件_QLCDNumber、ProgressBar、Calendar

文章目录 前言LCD NumberProgressBarCalendar Widget 小结 前言 本文将会向你介绍显示类控件中QLCDNumber显示数字、ProgressBar进度条、Calendar日历 LCD Number QLCDNumer 是⼀个专门用来显示数字的控件. 类似于 “老式计算器” 的效果. 属性说明intValueQLCDNumber 显示…...

--spring.profiles.active=prod

rootproduct-qualification:~# ps -ef | grep java root 5110 1 3 16:57 ? 00:00:54 java -jar productQualification.jar --spring.profiles.activeprod root 6476 5797 0 17:26 pts/0 00:00:00 grep --colorauto java好的,你使用 ps …...

深入解析JVM中对象的创建过程

1. 引言 对象是面向对象编程的核心概念之一,它们封装了数据和行为,构成了应用程序的基本构建块。然而,在Java语言中,每当使用new关键字或其他方式创建一个新对象时,背后发生了什么?这个问题的答案隐藏在JV…...

使用开源在线聊天工具Fiora轻松搭建个性化聊天平台在线交流

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家:人工智能教程 文章目录 前言1.关于Fiora2.安装Docker3.本地部署Fiora4.使用Fiora5.cpolar内网穿透工具安装6.创建远程连接公网地址7.固定Uptime …...

ffmpeg之显示一个yuv照片

显示YUV图片的步骤 1.初始化SDL库 目的:确保SDL库正确初始化,以便可以使用其窗口、渲染和事件处理功能。操作:调用 SDL_Init(SDL_INIT_VIDEO) 来初始化SDL的视频子系统。 2.创建窗口用于显示YUV图像: 目的:创建一个…...

MySQL中Performance Schema库的详解(下)

昨天说了关于SQL语句相关的,今天来说说性能相关的,如果没有看过上篇请点传送门https://blog.csdn.net/2301_80479959/article/details/144693574?fromshareblogdetail&sharetypeblogdetail&sharerId144693574&sharereferPC&sharesource…...

【Rust自学】7.1. Package、Crate和定义Module

喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 7.1.1. Rust的代码组织 代码组织主要包括: 那些细节可以对外暴露,而哪些细节是私有的在作用域内哪些名称有效… …...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

HTML 列表、表格、表单

1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...