【Spring】Spring 中事务的实现
目录
- 1.编程式事务(手动编写代码)
- 2.声明式事务(利用注解)
- 2.1 @Transactional作用范围
- 2.2 @Transactional参数说明
- 2.3 @Transactional工作原理
- 3.Spring 中设置事务隔离级别
- 3.1 事务四大特性ACID
- 3.2 事务的隔离级别
- 3.2 Spring中设置事务的隔离级别
- 4.Spring 中事务传播机制
- 4.1 事务的传播机制是什么
- 4.2 传播机制和隔离级别的作用
- 4.3事务传播机制的种类
- 5.Spring 中事务传播机制的使用
- 5.1 支持当前事务REQUIRED
- 5.2 不支持当前事务REQUIRES_NEW
- 5.3 不支持当前事务NEVER抛异常
- 5.4 NESTED嵌套事务
- 5.5 嵌套事务和加入事务的区别
事务定义:将一组操作封装成⼀个执⾏单元(封装到⼀起),要么全部成功,要么全部失败
Spring 中的事务操作分为两类:
- 编程式事务(⼿动写代码操作事务)。
- 声明式事务(利⽤注解⾃动开启和提交事务)。
1.编程式事务(手动编写代码)
编程式事务有三个步骤:
- 开启事务(获取事务)。
- 提交事务。
- 回滚事务。
SpringBoot 内置了两个对象:
DataSourceTransactionManager ⽤来获取事务(开启事务)、提交或回滚事务
TransactionDefinition 是事务的属性,在获取事务的时候需要将TransactionDefinition 传递进去从⽽获得⼀个事务 TransactionStatus
实现代码如下:
package com.example.mybatisdemo.controller;import com.example.mybatisdemo.model.User;
import com.example.mybatisdemo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 手动提交事务*/
@Slf4j
@RequestMapping("/trans")
@RestController
public class TransactionController {@Autowiredprivate UserService userService;//获取数据库事务管理器@Autowiredprivate DataSourceTransactionManager dataSourceTransactionManager;//数据库事务默认配置@Autowiredprivate TransactionDefinition transactionDefinition;@RequestMapping("/addUser")public Integer addUser(String username,String password){//获取一个事务TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition);User user=new User(username,password);Integer result = userService.insert(user);log.info("影响行数:"+result);//回滚到transaction状态//dataSourceTransactionManager.rollback(transaction);//事务提交dataSourceTransactionManager.commit(transaction);return result;}
}
2.声明式事务(利用注解)
声明式事务的实现很简单,只需要在需要的⽅法上添加 @Transactional 注解就可以实现了,⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务,具体实现代码如下:
/*** 使用注解提交事务*/
@Slf4j
@RequestMapping("/trans2")
@RestController
public class TransactionController2 {@Autowiredprivate UserService userService;@Transactional //事务注解//在遇到运行时异常(RuntimeException)和error才会回滚,非运行时异常不回滚@RequestMapping("/addUser")public Integer addUser(String username,String password){User user=new User(username,password);Integer result = userService.insert(user);log.info("影响行数:"+result);//发生异常时,事务会回滚//int a=10/0;return result;}
}
补充:如果异常被捕获了,事务不会回滚,代码示例:
@Transactional@RequestMapping("/addUser3")public Integer addUser3(String username,String password) throws Exception {User user=new User(username,password);Integer result = userService.insert(user);log.info("影响行数:"+result);try {int a=10/0;} catch (Exception e){e.printStackTrace();}return result;}
2.1 @Transactional作用范围
@Transactional 可以⽤来修饰⽅法或类:
-
修饰⽅法时:需要注意只能应⽤到 public ⽅法上,否则不⽣效。推荐此种⽤法。
-
修饰类时:表明该注解对该类中所有的 public ⽅法都⽣效
2.2 @Transactional参数说明

rollbackFor和noRollbackFor示例代码:
/*** 指定异常不回滚* @param username* @param password* @return*/@Transactional(noRollbackFor = ArithmeticException.class)@RequestMapping("/addUser")public Integer addUser1(String username,String password){User user=new User(username,password);Integer result = userService.insert(user);log.info("影响行数:"+result);//发生异常时,事务会回滚//int a=10/0;return result;}/*** 指定异常回滚* @param username* @param password* @return*/@Transactional(rollbackFor = Exception.class) //所有异常都回滚@RequestMapping("/addUser2")public Integer addUser2(String username,String password) throws Exception {User user=new User(username,password);Integer result = userService.insert(user);log.info("影响行数:"+result);throwException();return result;}public void throwException() throws Exception{throw new IOException();}
2.3 @Transactional工作原理
@Transactional 是基于 AOP 实现的,AOP ⼜是使⽤动态代理实现的。如果⽬标对象实现了接⼝,默认情况下会采⽤ JDK 的动态代理,如果⽬标对象没有实现了接⼝,会使⽤ CGLIB 动态代理。
@Transactional 在开始执⾏业务之前,通过代理先开启事务,在执⾏成功之后再提交事务。如果中途遇到的异常,则回滚事务。
@Transactional 实现思路预览:

3.Spring 中设置事务隔离级别
3.1 事务四大特性ACID
事务有4 ⼤特性(ACID),原⼦性、持久性、⼀致性和隔离性,具体概念如下:
原⼦性(Atomicity,或称不可分割性):⼀个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执⾏过程中发⽣错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执⾏过⼀样。
⼀致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写⼊的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以⾃发性地完成预定的⼯作。
持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
隔离性(Isolation,⼜称独⽴性):数据库允许多个并发事务同时对其数据进⾏读写和修改的能⼒,隔离性可以防⽌多个事务并发执⾏时由于交叉执⾏⽽导致数据的不⼀致。事务隔离分为不同级别,包括读未提交(Readuncommitted)、读提交(read committed)、可重复读(repeatable read)和串⾏化(Serializable)。
3.2 事务的隔离级别
事务的隔离级别有四种:
- READ UNCOMMITTED:读未提交,也叫未提交读,该隔离级别的事务可以看到其他事务中未提交的数据。该隔离级别因为可以读取到其他事务中未提交的数据,⽽未提交的数据可能会发⽣回滚,因此我们把该级别读取到的数据称之为脏数据,把这个问题称之为脏读。
- READ COMMITTED:读已提交,也叫提交读,该隔离级别的事务能读取到已经提交事务的数据,因此它不会有脏读问题。但由于在事务的执⾏中可以读取到其他事务提交的结果,所以在不同时间的相同 SQL 查询中,可能会得到不同的结果,这种现象叫做不可重复读。(Oracle默认隔离级别)
- REPEATABLE READ:可重复读,是 MySQL 的默认事务隔离级别,它能确保同⼀事务多次查询的结果⼀致。但也会有新的问题,⽐如此级别的事务正在执⾏时,另⼀个事务成功的插⼊某条数据,但因为它每次查询的结果都是⼀样的,所以会导致查询不到这条数据,⾃⼰重复插⼊时⼜失败(因为唯⼀约束的原因)。明明在事务中查询不到这条信息,但⾃⼰就是插⼊不进去,这就叫幻读(Phantom Read)。(MySQL默认隔离级别)
- SERIALIZABLE:序列化,事务最⾼隔离级别,它会强制事务排序,使之不会发⽣冲突,从⽽解决了脏读、不可重复读和幻读问题,但因为执⾏效率低,所以真正使⽤的场景并不多。

● 脏读:⼀个事务读取到了另⼀个事务修改的数据之后,后⼀个事务⼜进⾏了回滚操作,从⽽导致第⼀个事务读取的数据是错误的。
● 不可重复读:⼀个事务两次查询得到的结果不同,因为在两次查询中间,有另⼀个事务把数据修改了。
● 幻读:⼀个事务两次查询中得到的结果集不同,因为在两次查询中另⼀个事务有新增了⼀部分数据。
3.2 Spring中设置事务的隔离级别
Spring 中事务隔离级别包含以下 5 种:
- Isolation.DEFAULT:以连接的数据库的事务隔离级别为主。
- Isolation.READ_UNCOMMITTED:读未提交,可以读取到未提交的事务,存在脏读。
- Isolation.READ_COMMITTED:读已提交,只能读取到已经提交的事务,解决了脏读,存在不可重复读。
- Isolation.REPEATABLE_READ:可重复读,解决了不可重复读,但存在幻读(MySQL默认级别)。
- Isolation.SERIALIZABLE:串⾏化,可以解决所有并发问题,但性能太低。
从上述介绍可以看出,相⽐于 MySQL 的事务隔离级别,Spring 的事务隔离级别只是多了⼀个
Isolation.DEFAULT(以数据库的全局事务隔离级别为主)
Spring 中事务隔离级别只需要设置 @Transactional ⾥的 isolation 属性即可,具体实现代码如下:
@RequestMapping("/save")
@Transactional(isolation = Isolation.SERIALIZABLE)
public Object save(User user) {// 业务实现
}
4.Spring 中事务传播机制
4.1 事务的传播机制是什么
先来看一个示例:

此时有3个事务,A调用了B和C,如果C事务执行失败,B事务执行成功,那么B最终能否成功,A能否成功???
答案是在不同的事务传播机制中,结果是不同的。
Spring 事务传播机制定义了多个包含了事务的⽅法,相互调⽤时,事务是如何在这些⽅法间进⾏传递的。
4.2 传播机制和隔离级别的作用
- 事务隔离级别是保证多个并发事务执⾏的可控性的(稳定性的)
- ⽽事务传播机制是保证⼀个事务在多个调⽤⽅法间的可控性的(稳定性的)。
举个例⼦:像新冠病毒⼀样,它有不同的隔离⽅式(酒店隔离还是居家隔离),是为了保证疫情可控,然⽽在每个⼈的隔离过程中,会有很多个执⾏的环节,⽐如酒店隔离,需要负责⼈员运送、物品运送、消杀原⽣活区域、定时核算检查和定时送餐等很多环节,⽽事务传播机制就是保证⼀个事务在传递过程中是可靠性的,回到本身案例中就是保证每个⼈在隔离的过程中可控的。
事务隔离级别解决的是多个事务同时调⽤⼀个数据库的问题,如下图所示:

⽽事务传播机制解决的是⼀个事务在多个节点(⽅法)中传递的问题,如下图所示:

4.3事务传播机制的种类
Spring 事务传播机制包含以下 7 种:
- Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加⼊该事务;如果当前没有事务,则创建⼀个新的事务。
- Propagation.SUPPORTS:如果当前存在事务,则加⼊该事务;如果当前没有事务,则以⾮事务的⽅式继续运⾏。
- Propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加⼊该事务;如果当前没有事务,则抛出异常。
- Propagation.REQUIRES_NEW:表示创建⼀个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部⽅法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部⽅法会新开启⾃⼰的事务,且开启的事务相互独⽴,互不⼲扰。
- Propagation.NOT_SUPPORTED:以⾮事务⽅式运⾏,如果当前存在事务,则把当前事务挂起。
- Propagation.NEVER:以⾮事务⽅式运⾏,如果当前存在事务,则抛出异常。
- Propagation.NESTED:如果当前存在事务,则创建⼀个事务作为当前事务的嵌套事务来运⾏;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED
以上 7 种传播⾏为,可以根据是否⽀持当前事务分为以下 3类:

5.Spring 中事务传播机制的使用
5.1 支持当前事务REQUIRED
正常情况演示:
先开启事务,插入用户,再插入日志:
@Transactional@RequestMapping("/addUser")public boolean addUser(String username,String password){//插入用户表User user=new User(username,password);userService.insert(user);//插入日志表UserLog userLog=new UserLog(username);userLogService.insertLog(userLog);return true;}
UserService实现代码:
@Transactional(propagation = Propagation.REQUIRED)public Integer insert(User user) {return userMapper.insert(user);}
UserLogService实现代码:
@Transactional(propagation = Propagation.REQUIRED)public Integer insertLog(UserLog userLog){return userLogMapper.insertLog(userLog);}
执行结果:数据库数据成功插入。
错误情况演示:
先开启事务,插入用户,再插入日志(插入日志异常):
UserLogService实现代码(出现除0异常):
@Transactional(propagation = Propagation.REQUIRED)public Integer insertLog(UserLog userLog){Integer result=userLogMapper.insertLog(userLog);int a=10/0;return result;}
执行结果:程序报错,数据库没有插入数据。
执行流程描述:
- UserService 中的保存⽅法正常执⾏完成。
- UserLogService 保存⽇志程序报错,因为使⽤的是 Controller 中的事务,所以整个事务回滚。
5.2 不支持当前事务REQUIRES_NEW
先开启事务,插入用户,再插入日志(插入日志异常):
@Transactional@RequestMapping("/addUser")public boolean addUser(String username,String password){//插入用户表User user=new User(username,password);userService.insert(user);//插入日志表UserLog userLog=new UserLog(username);userLogService.insertLog(userLog);return true;}
UserService实现代码:
@Transactional(propagation = Propagation.REQUIRES_NEW)public Integer insert(User user) {return userMapper.insert(user);}
UserLogService实现代码:
@Transactional(propagation = Propagation.REQUIRES_NEW)public Integer insertLog(UserLog userLog){Integer result=userLogMapper.insertLog(userLog);int a=10/0;return result;}
执行结果:用户表数据插入成功,日志表数据插入失败
原因:

5.3 不支持当前事务NEVER抛异常
先开启事务,插入用户,再插入日志(插入日志异常):
UserService实现代码:
@Transactional(propagation = Propagation.NEVER)public Integer insert(User user) {return userMapper.insert(user);}
UserLogService实现代码:
@Transactional(propagation = Propagation.NEVER)public Integer insertLog(UserLog userLog){Integer result=userLogMapper.insertLog(userLog);int a=10/0;return result;}
执行结果:程序报错,执行失败,数据库没有插入数据。
5.4 NESTED嵌套事务
先开启事务,插入用户,再插入日志(插入日志异常):
UserService实现代码:
@Transactional(propagation = Propagation.NESTED)public Integer insert(User user) {return userMapper.insert(user);}
UserLogService实现代码:
@Transactional(propagation = Propagation.NESTED)public Integer insertLog(UserLog userLog){Integer result=userLogMapper.insertLog(userLog);int a=10/0;return result;}
执行结果:执行失败,数据库没有插入数据。
代码①:现在修改一下UserLogService实现代码(加入回滚):
@Transactional(propagation = Propagation.NESTED)public Integer insertLog(UserLog userLog){Integer result=userLogMapper.insertLog(userLog);try {int a = 10 / 0;}catch (Exception e){//设置回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return result;}
执行结果:日志表插入成功,用户表插入失败
原因:在UserLogService加入部分回滚,用户表运行成功,日志表回滚了。
代码②:现在修改一下UserLogService实现代码(将NESTED改为REQUIRED):
@Transactional(propagation = Propagation.REQUIRED)public Integer insertLog(UserLog userLog){Integer result=userLogMapper.insertLog(userLog);try {int a = 10 / 0;}catch (Exception e){//设置回滚TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return result;}
执行结果:数据表没有插入数据
原因:日志表回滚,用户表也回滚了
5.5 嵌套事务和加入事务的区别
由上面代码①和代码②可得:
嵌套事务(NESTED)和加⼊事务(REQUIRED )的区别:
- 整个事务如果全部执⾏成功,⼆者的结果是⼀样的。
- 如果事务执⾏到⼀半失败了,那么加⼊事务整个事务会全部回滚;⽽嵌套事务会局部回滚,不会影响上⼀个⽅法中执⾏的结果。
相关文章:
【Spring】Spring 中事务的实现
目录 1.编程式事务(手动编写代码)2.声明式事务(利用注解)2.1 Transactional作用范围2.2 Transactional参数说明2.3 Transactional工作原理 3.Spring 中设置事务隔离级别3.1 事务四大特性ACID3.2 事务的隔离级别3.2 Spring中设置事…...
Linux 学习记录60(ARM篇)
Linux 学习记录60(ARM篇) 本文目录 Linux 学习记录60(ARM篇)一、SPI总线1. 概念2. 硬件连接 二、SPI总线协议三、SPI总线通信模式四、对比IIC总线和SPI总线1. 相同点2. 不同点 思维导图 一、SPI总线 1. 概念 1、SPI总结是Motorola首先提出的全双工三线/四线同步串行总线 2、采…...
尚硅谷大数据项目《在线教育之采集系统》笔记002
视频地址:尚硅谷大数据项目《在线教育之采集系统》_哔哩哔哩_bilibili 目录 P032 P033 P033 P034 P035 P036 P032 P033 # 1、定义组件,为各组件命名 a1.sources r1 a1.channels c1 a1.sinks - k1# 2、配置sources,描述source a1.sour…...
校园跑腿小程序功能分享
提起校园跑腿小程序大家都不陌生,尤其是对上大学的伙伴们来说,更是熟悉得不能再熟悉了,和我们的生活息息相关,密不可分。 对于现在的年轻人来说,网购是非常简单和方便的一种购物方式,随之快递也会越来越多。在我们国家…...
PHP8的变量-PHP8知识详解
昨天我们讲解了PHP8的常量,今天讲解PHP8的变量。常量有定义常量和预定义常量,变量呢?那就没有定义变量了,那叫给变量赋值,但是还是有预定义变量的。下面就给大家讲解什么是变量、变量赋值及使用及预定义变量。 一、什么…...
图解TCP 三次握手和四次挥手的高频面试题(2023最新版)
大家好,最近重新整理了一版 TCP 三次握手和四次挥手的面试题(2023最新版)。 ----- 任 TCP 虐我千百遍,我仍待 TCP 如初恋。 巨巨巨巨长的提纲,发车!发车! img TCP 基本认识 TCP 头格式有哪些…...
【mysql】Win10安装配置MySQL8.0简要
下载 MySQL官网下载安装包 安装...
SQL SERVER使用发布订阅同步数据库遇到的坑
可能遇到的各种坑 1.在执行 xp_cmdshell 的过程中出错。调用 ‘CreateProcess’ 失败,错误代码: ‘5’ 网上有各种解决办法,包括改本地安全策略,将sql server服务的网络权限改为本机系统,改cmd用户的读写权限,退出360…...
3个命令定位CPU飙高
top 指令找出消耗CPU最厉害的那个进程的pid top -H -p 进程pid 找出耗用CPU资源最多的线程pid printf ‘0x%x\n’ 线程pid 将线程pid转换为16进制 结合jstack 找出哪个代码有问题 jstack 进程pid | grep 16进制的线程pid -A 多少行日志 jstack 进程pid | grep 16进制的线程…...
Java版知识付费 Spring Cloud+Spring Boot+Mybatis+uniapp+前后端分离实现知识付费平台免费搭建
提供职业教育、企业培训、知识付费系统搭建服务。系统功能包含:录播课、直播课、题库、营销、公司组织架构、员工入职培训等。 提供私有化部署,免费售后,专业技术指导,支持PC、APP、H5、小程序多终端同步,支持二次开发…...
使用多数据源dynamic-datasource-spring-boot-starter遇到的问题记录
记录使用多数据源dynamic-datasource-spring-boot-starter遇到的问题: 1、工程启动失败 缺少clickhouse连接驱动,引入对应的maven依赖 <!--ck连接驱动--><dependency><groupId>ru.yandex.clickhouse</groupId><artifactId>…...
构建语言模型:BERT 分步实施指南
学习目标 了解 BERT 的架构和组件。了解 BERT 输入所需的预处理步骤以及如何处理不同的输入序列长度。获得使用 TensorFlow 或 PyTorch 等流行机器学习框架实施 BERT 的实践知识。了解如何针对特定下游任务(例如文本分类或命名实体识别)微调 BERT。为什么我们需要 BERT? 正…...
⛳ Java多线程 一,线程基础
线程基础 ⛳ Java多线程 一,线程基础🐾 一,线程基础💭 1.1,什么是程序,进程,线程🏭 1.2,什么是并行和并发👣 1.3,线程使用的场景🎨 1.…...
【iOS】多线程 锁问题总结
文章目录 前言1. 你理解的多线程优点缺点 2. atomic 和 nonatomic 的区别及其作用3. GCD的队列类型 - 三种队列类型4. GCD的死锁问题5. 多线程之间的区别和联系6. 进程和线程?进程间的通信方式线程间的通信方式 6. iOS的线程安全手段如何保证 前言 iOS 锁和多线程的…...
Pytorch深度学习-----神经网络之池化层用法详解及其最大池化的使用
系列文章目录 PyTorch深度学习——Anaconda和PyTorch安装 Pytorch深度学习-----数据模块Dataset类 Pytorch深度学习------TensorBoard的使用 Pytorch深度学习------Torchvision中Transforms的使用(ToTensor,Normalize,Resize ,Co…...
Docker啥是数据持久化?
文章目录 数据持久化数据卷相关命令创建读写数据卷创建只读数据卷数据卷共享数据卷容器实现数据卷共享nginx实现数据卷共享nfs总结 Dockerfile持久化Dockerfile方式docker run总结 数据持久化 在容器层的 UnionFS(联合文件系统)中对文件/目录的任何修…...
CGAL 线段简化算法(2D)
文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 线段简化是指:在减少一组折线中顶点数量的同时,尽可能保持整体形状的过程。CGAL中提供了一种迭代算法:通过从一条折线上移除顶点 q q q,迭代地将边 ( p , q...
在CentOS 7上挂载硬盘到系统的步骤及操作
目录 1:查询未挂载硬盘2:创建挂载目录3:检查磁盘是否被分区4:格式化硬盘5:挂载目录6:检查挂载状态7:设置开机自动挂载总结: 本文介绍了在CentOS 7上挂载硬盘到系统的详细步骤。通过确…...
螺旋矩阵(JS)
螺旋矩阵 题目 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n 3 输出:[[1,2,3],[8,9,4],[7,6,5]]示例 2: 输入ÿ…...
C#常用数学插值法
目录 1、分段线性插值 2、三次样条插值 3、拉格朗日插值 (1)一元全区间不等距插值 (2)一元全区间等距插值 4、埃尔米特插值 (1)埃尔米特不等距插值 (2)埃尔米特等距插值 1、…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
规则与人性的天平——由高考迟到事件引发的思考
当那位身着校服的考生在考场关闭1分钟后狂奔而至,他涨红的脸上写满绝望。铁门内秒针划过的弧度,成为改变人生的残酷抛物线。家长声嘶力竭的哀求与考务人员机械的"这是规定",构成当代中国教育最尖锐的隐喻。 一、刚性规则的必要性 …...
