spring--事务详解
spring事务
什么是事务
-
我们常说的事务,一般指数据库事务。
-
数据库事务是指 一个逻辑工作单元中执行的一系列(数据库操作),要么一起成功,要么一起失败
-
当工作单元中的所有操作全部正确完成时,工作单元的操作才会生效,如果检测到一个错误,程序执行回滚操作,恢复原状,要么都执行,要么都不执行
-
逻辑工作单元就是一个不可分割的操作序列,操作序列就是一系列的数据库操作
-
Spring的事务就是对数据库事务的封装,最后本质的实现还是在数据库,假如数据库不支持事务的话,spring的事务是没有作用的
-
数据库的事务有开启、执行、提交、回滚,还有关闭,是数据库连接操作
事务ACID
-
原子性(Atomicity)
-
整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(ROLLBACK)到事务开始前的状态,就像这个事务从来没有执行过一样。原子性由undo log 日志来保证
-
undo log 日志:在MySQL数据库运行的过程中,会在后台生成日志,例如:在完成订单事务时,你写入insert 语句时,undo log日志会在后台为你生成一个对应的delete语句,当事务执行失败后,在回滚过程中只需要在后台执行delete语句即可
-
-
一致性(Consistency)
-
事务前后的数据完整性要保持一致
-
一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。也就是说:如果事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是最终一致性,
-
使用业务的最终目的,由业务代码正确逻辑保证
-
一致性是事务的最终目标,原子性,隔离性,持久性是实现一致性的手段
-
-
隔离性(Isolation)
-
针对多个用户进行操作,主要排除其他事务对本次事务的影响
-
多个用户并发访问数据库时,数据库为每个用户开启的事务,不能被其他事务的操作数据所干扰
-
-
持久性(Durability)
-
事务一旦提交就不可逆
-
事务没有提交,恢复到原状态,在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库或文件之中,并不会被回滚。就算是宕机或者断电,也不会出现丢失的情况。
-
持久性由redo log日志来保证
-
三大基础设施
spring中对事务的支持提供三大基础设施
-
PlatformTransactionManager
-
TransactionDefinition
-
TransactionStatus
事务管理器(PlatformTransactionManager)
Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。 Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。此接口的内容如下:
Public interface PlatformTransactionManager()...{ // 由TransactionDefinition得到TransactionStatus对象TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; // 提交Void commit(TransactionStatus status) throws TransactionException; // 回滚Void rollback(TransactionStatus status) throws TransactionException; }
从这里可知具体的具体的事务管理机制对Spring来说是透明的,它并不关心那些,那些是对应各个平台需要关心的,所以Spring事务管理的一个优点就是为不同的事务API提供一致的编程模型,如JTA、JDBC、Hibernate、JPA。下面介绍JDBC框架实现事务管理的机制。
使用Spring管理事务,注意头文件的约束导入 : tx
<xmlns:tx="http://www.springframework.org/schema/tx"http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd">
事务管理器
-
无论使用Spring的哪种事务管理策略(编程式或者声明式)事务管理器都是必须的。
-
就是 Spring的核心事务管理抽象,管理封装了一组独立于技术的方法。
JDBC事务
<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean>
配置好事务管理器后我们需要去配置事务的通知
<!--配置事务通知--><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!--配置哪些方法使用什么样的事务,配置事务的传播特性--><tx:method name="add" propagation="REQUIRED"/><tx:method name="delete" propagation="REQUIRED"/><tx:method name="update" propagation="REQUIRED"/><tx:method name="search*" propagation="REQUIRED"/><tx:method name="get" read-only="true"/><tx:method name="*" propagation="REQUIRED"/></tx:attributes></tx:advice>
基本事务属性的定义(TransactionDefinition)
上面讲到的事务管理器接口PlatformTransactionManager通过getTransaction(TransactionDefinition definition)方法来得到事务,这个方法里面的参数是TransactionDefinition类,这个类就定义了一些基本的事务属性。
事务属性是实现事务特性的重要组成部分
事务属性一般指的就是就是spring的事务属性,常用的有五种spring事务属性
隔离性
就是事务的隔离级别,分为 read uncommitted(读未提交),read committed(读已提交),repeatable read(可重复读), Serialization(串行化),不过spring事务会在这个基础上多一种default(就是已连接的数据库级别为准)MySQL的默认隔离级别是repeatable read,所以default就是可重复读。
注意事项:数据库事务中的隔离性是特征与目标,spring事务中的隔离性是实现该目标的方式
传播性
事务传播行为是为了解决业务层方法之间相互调用的事务问题,当一个事务方法被另一个事务方法调用时(A方法调用B方法)当方法之间相互调用时,事务会以何种状态存在,这些规则就涉及到事物的传播性
三条规则来定义这七种传播性:
-
创建新事务还是加入当前事务
-
多个事务并存的时候是否会互相影响
-
有实物抛异常,还是没事务抛异常
public enum Propagation {REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),NEVER(TransactionDefinition.PROPAGATION_NEVER),NESTED(TransactionDefinition.PROPAGATION_NESTED);private final int value;Propagation(int value) {this.value = value;}public int value() {return this.value;}
是spring特有的事务管理概念,一共有七种传播方式:
传播性 | 描述 |
---|---|
REQUIRED(默认) | 如果当前存在事务,则加入到这个事务,如果当前没有事务,就新建一个事务, |
SUPPORTS | 如果当前存在事务,则加入到这个事务,如果没有当前事务,就以非事务方法执行 |
MANDATORY | 如果当前存在事务,则加入到这个事务,如果当前没有事务,就抛出异常。 |
REQUIRES_NEW | 创建一个新的事务,如果当前存在事务,把当前事务挂起。(脱离当前事务的影响) |
NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。(脱离当前事务的影响) |
NEVER | 以非事务方式执行操作,如果当前事务存在,则抛出异常。 |
NESTED | 如果当前存在事务,则创建一个新的事务作为当前事务的嵌套事务来执行,如果没有,则新建一个事务 |
代码展示:
package com.lyc.service;import com.lyc.mapper.UserMapperIpml;import com.lyc.pojo.User;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import org.springframework.transaction.support.TransactionSynchronizationManager;import javax.annotation.Resource;import java.util.List;@Servicepublic class TxAService {@Resourceprivate TxBService bService;@Resourceprivate UserMapperIpml userMapperIpml;@Transactional //添加事务注解,默认是只读事务,相当于开启了一个事务public void handle1(int id){User user = userMapperIpml.selectUserById(id);userMapperIpml.updateUser(user);String name = TransactionSynchronizationManager.getCurrentTransactionName();System.out.println("handle1加入的事务名称:"+name);// 调用bServicebService.handle2(id);if (1==1){throw new RuntimeException("异常");}}}
package com.lyc.service;import com.lyc.mapper.UserMapperIpml;import com.lyc.pojo.User;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import org.springframework.transaction.support.TransactionSynchronizationManager;import javax.annotation.Resource;@Servicepublic class TxBService {@Resourceprivate UserMapperIpml userMapperIpml;//无论是否加上@Transactional注解,都会开启事务,但是只有加上@Transactional注解的方法才会回滚@Transactional(propagation = Propagation.SUPPORTS)public void handle2(int id){User user = userMapperIpml.selectUserById(id + 1);userMapperIpml.updateUser(user);// 获取当前事务的名称String name = TransactionSynchronizationManager.getCurrentTransactionName();System.out.println("当前事务的名称:" + name);if(true){throw new RuntimeException("事务回滚");}}}
代码分析:
在测试中,handle1事务方法里面调用handle2事务方法
REQUIRED(默认)
如果当前存在事务,则加入到这个事务,如果当前没有事务,就新建一个事务,
在handle2方法中,无论加不加transactional注解都会加入到handle1事务中,而不会自己创建,而在handle1方法中,事务成功回滚,在此次操作中handle1方法和handle2方法的事务都是handle1。
如果handle1方法没有事务(没有@Transactional),handle2方法有事务(由@Transactional),则会新创建一个事务handle2,handle1方法没有事务,handle2方法的事务为handle2
SUPPORTS
如果当前存在事务,则加入到这个事务,如果没有当前事务,就以非事务方法执行
handle1方法如果有事务,handle2方法的事务传播性(行为)为SUPPORTS,则handle1和handle2方法的事务都为handle1,如果handle1方法没有事务,handle2方法则以非事务的方式继续运行,即无法进行事务回滚,也不会建立事务
MANDATORY
如果当前存在事务,则加入到这个事务,如果当前没有事务,就抛出异常。
handle1方法如果有事务,handle2方法的事务传播性(行为)为MANDATORY,则handle1和handle2方法的事务都为handle1,如果handle1方法没有事务,handle2方法则直接抛出异常
REQUIRES_NEW
创建一个新的事务,如果当前存在事务,把当前事务挂起。(脱离当前事务的影响)
handle1方法如果有事务,handle2方法的事务传播性(行为)为REQUIRE_NEW,则handle2会新建一个事务并脱离前面一个事务的影响,独立出来,如果handle1事务回滚,handle2事务不会回滚
比较适合 有方法大概率出错但又不想影响到其他方法的正常执行
NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。(脱离当前事务的影响)
handle1方法无论是否有事务,handle2方法的事务传播性(行为)为NOT_SUPPORTED,handle2都不会加入这个事务,也不会自己创建事务,handle2永远处于无事务的状态,也不会回滚
NEVER
以非事务方式执行操作,如果当前事务存在,则抛出异常。
handle2方法的事务传播性(行为)为NEVER,如果handle2存在事务就会抛异常
NESTED
如果当前存在事务,则创建一个新的事务作为当前事务的嵌套事务来执行,如果没有,则新建一个事务
如果handle1报错,则handle2也报错(外面的大事务会影响里面的小事务),即handle1方法报错回滚,则handle2方法也会回滚,如果handle2出现了异常回滚,只需要将在handle1方法中的handle2异常捕获,则handle1方法不会出现异常,不会回滚。
如果handle1方法没有事务(没有@Transactional),handle2方法有事务(由@Transactional),则会新创建一个事务handle2,handle1方法没有事务,handle2方法的事务为handle2
REQUIRES_NEW与NESTED的区别:
回滚规则
默认情况下,事务只有遇到运行期异常(RunException的子类)以及Error才会回滚,在遇到检查型(checkedException)异常时不会回滚
例如发生IOException并不会导致事务回滚,如果想要在发生IOException时也想触发事务回滚
代码展示:
@Transcational(rollbackFor = IOException.class)public void handle2(){jdbcTemplate.update("update user set money = ? where username = ?;",1,"zhangsan");accountService.handle1();}
我们也可以指定在发生某些异常时不回滚,例如当系统抛出AirthmeticException异常不触发事务回滚
代码展示:
@Transcational(norollbackFor = AirthmeticException.class)public void handle2(){jdbcTemplate.update("update user set money = ? where username = ?;",1,"zhangsan");accountService.handle1();}
是否只读
一般用在业务方法中全部都是查询的代码,没有增删改,作用:
让这些相同的查询,可以查到相同的结果。
语法:
@Transactional(readOnly = true) //
只要在Transactional注解中添加(readOnly = true),就能让一个事务中相同的查询查到相同的结果(可重复读),添加之后,事务就会知道这只是一个只读的事件,就可以获得数据库与驱动的优化,性能会更好
超时时间
通过设置一个事务允许执行的最长时间,超过这个时间的限制,但是事务还没有提交,就会自动回滚
语法:
@Transactional(timeout = 10) // 10秒内事务没有提交,则自动回滚
事务状态(TransactionStatus)
上面讲到的调用PlatformTransactionManager接口的getTransaction()的方法得到的是TransactionStatus接口的一个实现,这个接口的内容如下:
public interface TransactionStatus{boolean isNewTransaction(); // 是否是新的事物boolean hasSavepoint(); // 是否有恢复点void setRollbackOnly(); // 设置为只回滚boolean isRollbackOnly(); // 是否为只回滚boolean isCompleted; // 是否已完成}
可以发现这个接口描述的是一些处理事务提供简单的控制事务执行和查询事务状态的方法,在回滚或提交的时候需要应用对应的事务状态。
spring中的事务管理
Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式事务管理
-
声明式事务:
-
一般情况下比编程式事务好用。
-
将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
-
将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。
-
-
编程式事务:
-
将事务管理代码嵌到业务方法中来控制事务的提交和回滚
-
缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码
-
编程式事务类似于JDBC事务的写法,需要将事务的代码嵌入到业务逻辑中,代码的耦合度较高
声明式事务通过AOP的思想,将事务与业务逻辑代码解耦(基于@Transactional注解或者基于XML配置)
编程式事务
通过PlatformTransactionManager或者TransactionTemplate可以实现编程式事务
在spring boot项目中,这两个对象spring boot会自动提供,直接使用即可
3.2.1 使用TransactionTemplate
采用TransactionTemplate和采用其他Spring模板,如JdbcTempalte和HibernateTemplate是一样的方法。它使用回调方法,把应用程序从处理取得和释放资源中解脱出来。如同其他模板,TransactionTemplate是线程安全的。代码片段:
TransactionTemplate tt = new TransactionTemplate(); // 新建一个TransactionTemplateObject result = tt.execute(new TransactionCallback(){ public Object doTransaction(TransactionStatus status){ updateOperation(); return resultOfUpdateOperation(); } }); // 执行execute方法进行事务管理
使用TransactionCallback()可以返回一个值。如果使用TransactionCallbackWithoutResult则没有返回值。
3.2.2 使用PlatformTransactionManager
示例代码如下:
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); //定义一个某个框架平台的TransactionManager,如JDBC、HibernatedataSourceTransactionManager.setDataSource(this.getJdbcTemplate().getDataSource()); // 设置数据源DefaultTransactionDefinition transDef = new DefaultTransactionDefinition(); // 定义事务属性transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED); // 设置传播行为属性TransactionStatus status = dataSourceTransactionManager.getTransaction(transDef); // 获得事务状态try {// 数据库操作dataSourceTransactionManager.commit(status);// 提交} catch (Exception e) {dataSourceTransactionManager.rollback(status);// 回滚}
在需要更精细化更复杂的事务控制,对性能有极致要求的场景下使用更合适,还有一些声明式事务失效的场景下使用,比如类的方法自调用,或者使用私有方法
声明式事务
底层实现
-
当目标类被spring管理时(即@Component,@Service,@controller,@Repository注解时),spring会为目标对象创建一个代理对象。代理对象负责拦截目标方法的调用,并在必要时应用事务管理(AOP思想)
-
代理对象内部包含一个事务拦截器TransactionInterceptor,负责处理事务相关的逻辑
-
事务拦截器会检查方法上是否添加了@Transactional注解,来决定是否应用事务
-
事务拦截器在目标方法执行前后应用事务通知,(前置通知和后置通知)在方法执行前,事务拦截器启动事务;在方法执行后,根据方法的执行结果决定事务的提交或回滚
代码展示:
package com.lyc.service;import com.lyc.mapper.UserMapperIpml;import com.lyc.pojo.User;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import org.springframework.transaction.support.TransactionSynchronizationManager;import javax.annotation.Resource;import java.util.List;@Servicepublic class TxAService {@Resourceprivate TxBService bService;@Resourceprivate UserMapperIpml userMapperIpml;@Transactional //添加事务注解,默认是只读事务,相当于开启了一个事务public void handle1(int id){User user = userMapperIpml.selectUserById(id);userMapperIpml.updateUser(user);String name = TransactionSynchronizationManager.getCurrentTransactionName();System.out.println("handle1加入的事务名称:"+name);// 调用bServicebService.handle2(id);if (1==1){throw new RuntimeException("异常");}}}
package com.lyc.service;import com.lyc.mapper.UserMapperIpml;import com.lyc.pojo.User;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import org.springframework.transaction.support.TransactionSynchronizationManager;import javax.annotation.Resource;@Servicepublic class TxBService {@Resourceprivate UserMapperIpml userMapperIpml;//无论是否加上@Transactional注解,都会开启事务,但是只有加上@Transactional注解的方法才会回滚@Transactional(propagation = Propagation.SUPPORTS)public void handle2(int id){User user = userMapperIpml.selectUserById(id + 1);userMapperIpml.updateUser(user);// 获取当前事务的名称String name = TransactionSynchronizationManager.getCurrentTransactionName();System.out.println("当前事务的名称:" + name);if(true){throw new RuntimeException("事务回滚");}}}
handle1方法开启了事务,会有一个前置通知和一个后置通知,而handle2方法同样有一个前置通知和一个后置通知,handle1调用handle2,则handle1有两个前置和两个后置,也就是说有两个高级切面,会被分成四个低级切面,目标方法在启动前,事务拦截器就会启动事务,也就是before1和before2都会启动事务方法,方法执行后,根据方法的执行结果来决定事务的提交和回滚,也就是after1和after2会执行提交或回滚。
-
事务拦截器还负责事务的传播行为
事务失效原因:
-
类的自调用:直接调用本类的方法,没有通过代理对象来调用方法,代理对象内部的事务拦截器不会拦截到这次行为。则不可能开启事务
-
使用私有方法:因为spring的事务管理是基于AOP实现的,AOP代理无法拦截目标对象内部的私有方法调用。直接没有代理对象
-
使用多线程:在主线程中开启的事务不会自动传播到其创建并执行的子线程中
-
如果事务回滚,将报错代码用try catch来进行捕获,事务就不会失效
-
其他比如定义事务属性传播性时定义的是REQUIRES_NEW(脱离当前事务),事务也不会受到影响
希望对大家有所帮助!
相关文章:
spring--事务详解
spring事务 什么是事务 我们常说的事务,一般指数据库事务。 数据库事务是指 一个逻辑工作单元中执行的一系列(数据库操作),要么一起成功,要么一起失败 当工作单元中的所有操作全部正确完成时,工作单元的…...
CSS实现DIV水平与垂直居中方法总结
大家好,欢迎来到程序视点!我是你们的老朋友.小二! CSS实现DIV水平与垂直居中方法总结 一、水平居中方案 标准方法 .center-div {margin-left: auto;margin-right: auto; }关键点:必须声明DOCTYPE(推荐XHTML 1.0 Tran…...
AI 助力 Python:长时序植被遥感动态分析与生态评估
技术点目录 Python遥感数据处理基础及AI大模型应用技巧常用共享数据资源介绍AI辅助下地球科学数据处理方法及python实现AI辅助下植被参数遥感反演基本原理及python实现AI辅助下地球科学数据分析方法及python实现AI辅助下植被物候提取与分析实践应用AI辅助下植被时空动态分析及p…...
卫星变轨轨迹和推力模拟(单一引力源)MATLAB
代码说明: 常量定义:定义了万有引力常数、地球和月球的质量、半径以及地月平均距离。初始状态设置:设置卫星的初始位置、速度和姿态,以及月球的初始位置。模拟循环:在循环中计算地球和月球对卫星的引力,模…...
2025华东杯B题华东杯数学建模思路代码成品讲解工序安排问题
完整内容请看文章最下面的推广群 我将展示完整的文章、代码和结果 工序安排问题 摘要 本文研究的核心是制造业中的工序安排优化问题,源自实际生产管理中常见的资源分配挑战。问题背景设定为一家拥有100名工人和三条相同服装生产线的成衣制造厂,涉及裁…...
Python的赋值操作都是引用吗?
Python的赋值操作都是引用吗? 一言以蔽之:Python的赋值本质都是引用传递,但不可变对象的表现类似于值传递,这是由对象不可变性造成的效果。(我非常确信这篇笔记说的内容都是正确的,这篇笔记是deepseekv3的…...
学习influxDB的安装和使用
influxDB的使用场景 nfluxDB 是一种时序数据库,时序数据库通常被用在监控场景,用来收集各个节点采集到的监控指标,以及监控指标产生的时间点.比如我们收集的主机的监控数据,可以通过查询语句,统计查询过去30分钟内cpu的平均使用率是多少. 相比关系型数据库与时序数…...
LeetCode209_长度最小的子数组
LeetCode209_长度最小的子数组 标签:#数组 #二分查找 #前缀和 #滑动窗口Ⅰ. 题目Ⅱ. 示例0. 个人方法:滑动窗口 标签:#数组 #二分查找 #前缀和 #滑动窗口 Ⅰ. 题目 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足…...
uniapp 实现时分秒 分别倒计时
效果 <view class"issue-price-countdown"> <CountDown :endTimestamp"1745996085000"></CountDown> </view> 引入组件 import CountDown from /components/CountDown.vue; <template> <view class&qu…...
ubuntu下一些环境配置
1、qhull sudo apt install qhull-bin libqhull-dev 2、cmake wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null echo "deb [signed…...
el-check-box多选框和el-select下拉框组合
<template><div><el-selectv-model"selectedValues"multiplecollapse-tagsplaceholder"请选择电压等级"change"handleChange"><el-option key"all" value"all" class"select-all-option">…...
SPSS PCA+判别分析
1, 主成分分析PCA 我们只要对数化的变量数据: (1)对数据进行标准化处理: 选择【分析】—【描述统计】—【描述】 添加要标准化的变量,勾选【将标准化值另存为变量(Z)】,再点确定 SPSS软件本身不…...
【阿里云大模型高级工程师ACP习题集】2.7 通过微调增强模型能力 (下篇)(⭐️⭐️⭐️ 重点章节!!!)
习题集: 【单选题】在阿里云大模型微调中,以下关于预训练和微调的说法,错误的是?( ) A. 预训练使用自监督/无监督学习方式 B. 微调通常在大规模通用数据集上进行 C. 预训练模型可以为下游任务提供初始模型 D. 微调能让模型适应具体的下游任务 【多选题】LoRA微调中,低秩…...
ag-grid-react 列表导出csv列表getDataAsCsv (自定义导出列表配置)自定义新增,修改导出内容
1.ag-grid-react getDataAsCsv 新增导出字段 方法:临时添加列再导出 你可以通过 columnApi.setColumnDefs() 临时添加需要导出的字段,然后再调用 getDataAsCsv,导出后再恢复原来的列。 import { useRef } from react; import { AgGridReac…...
深度解析:Vue.js 性能优化全景指南(从原理到实践)
前言 随着 Vue.js 应用复杂度提升,性能问题逐渐成为制约用户体验的瓶颈。本文将系统性地剖析 Vue.js 性能优化的 核心原理、关键技巧、工具链支持,并通过真实案例演示如何提升大型应用的运行时性能与加载效率。 一、渲染层优化:减少不必要的…...
Linux -- 操作系统
一、冯•诺依曼体系结构 1、概念 # 在计算机发展历程中,核心作用就是解决人类问题。为了实现这一目标,计算机系统需具备特定结构和功能。 首先,计算机要配备输入设备,如鼠标、键盘、摄像头、话筒、磁盘(文件读取&…...
(初探)强化学习路径规划的理论基础与代码实现
一、强化学习路径规划的核心理论 1.1 马尔可夫决策过程(MDP)框架 理论基础: 路径规划问题可以建模为马尔可夫决策过程(Markov Decision Process, MDP),由五元组(S, A, P, R, γ)定义。其中,S&…...
分布式链路ID实现
实现原理 api入口或者网关处生成traceId,调用服务时优先检查是否头部带有traceId,有则复用,没有则生成 实现方式 处理api相关traceId 1.通过filter复用或者生成traceId,并且将traceId输入到响应头中 import java.io.IOExcept…...
Java @Transactional事物隔离级别和默认值详解
在 Java 开发中,Transactional 注解是 Spring 框架中用于管理事务的重要工具。它提供了多种配置选项,其中事务隔离级别是一个关键属性。本文将深入探讨 Transactional 注解的隔离级别默认值,并通过具体代码示例帮助你更好地理解和应用事务隔离…...
ComputeShader绘制全屏纯色纹理
参考 Getting Started With Compute Shaders In Unity 环境 Win10 Unity20194.40 全屏纯色纹理示例 使用ComputerShader逐个像素设置颜色 ComputeShader脚本 设置纹理颜色 #pragma kernel CSMainRWTexture2D<float4> Result;//纹理 half4 solidColor;//颜色[numth…...
关于 MCP 的理论知识学习
文章目录 1. 写在最前面2. 基本概念2.1 Why MCP2.1.1 大模型访问的局限2.1.2 过渡阶段—Function Call2.1.3 当前阶段— MCP 3. 碎碎念4. 参考资料 1. 写在最前面 最近有一项任务是写旧版本迁移到新版本的支持文档,文档的编写是借助于 cursor 帮忙写的。但是实现的…...
关于vue+iview中tabs嵌套及实际应用
最近在用vueiview框架做项目,在实际做项目中根据需求用到iview中的tabs标签页嵌套以及标签页增加删除功能。想着记录下来,以后可能会再用到。下面是页面。由于是公司的项目具体有些地方我会打码,不影响阅读! 1607751577(1).jpg ta…...
26考研——输入/输出系统_I/O 方式_DMA 方式(7)
408答疑 文章目录 三、I/O 方式DMA 方式DMA 方式的特点DMA 控制器的组成DMA 的传送方式停止 CPU 访存周期挪用DMA 与 CPU 交替访存 示例分析DMA 的传送过程 DMA 方式和中断方式的区别 四、参考资料鲍鱼科技课件26王道考研书 三、I/O 方式 DMA 方式 DMA 方式是一种完全由硬件进…...
处理vue3热加载后axios的请求重复访问的问题
在请求拦截上加上判断,热加载时清空拦截器 if (import.meta.hot) { const interceptorsRe axios.interceptors.response.handlers; const interceptorsRq axios.interceptors.request.handlers; interceptorsRe .length 0; // 清空已有响应拦截器 interceptorsR…...
【教学类-102-21】蝴蝶三色图作品3——异型书蝴蝶“满格变形图”一页2图、一页4图
前期设计 将蝴蝶撑满整个单元格,满格变形图。确保蝴蝶图案最大化 【教学类-102-20】蝴蝶三色图作品2——卡纸蝴蝶“满格变形图”(滴颜料按压对称花纹、原图切边后变形放大到A4横版最大化)-CSDN博客文章浏览阅读572次,点赞7次,收藏3次。【教学类-102-20】蝴蝶三色图作品2…...
【昇腾】Benchmark
1. MindIE 服务化 1.1 环境准备 镜像传送门 参数说明: device用于挂载卡,下面的例子是挂载了8张卡 倒数第二行的镜像名称记得修改 docker run -itd --privileged --namemindie --nethost \--shm-size 500g \--device/dev/davinci0 \--device/dev/da…...
【阿里云大模型高级工程师ACP学习笔记】2.7 通过微调增强模型能力 (下篇)(⭐️⭐️⭐️ 重点章节!!!)
学习目标 特别说明:由于这一章节是2025年3月官方重点更新的部分,新增内容非常多,因此我不得不整理成上、下两篇,方便大家参考。 备考阿里云大模型高级工程师ACP认证时,深入钻研《2.7通过微调增强模型能力(下篇)》,期望达成以下目标: 掌握高效微调技术:深入理解预训练与…...
【RustDesk 】中继1:压力测试 Python 版 RustDesk 中继服务器
测试 Python 版 RustDesk 中继服务器 测试我们实现的中继服务器有几种方法,从简单到复杂依次如下: 1. 基本连接测试客户端 创建一个简单的测试客户端来验证中继服务器的基本功能: 2. 用两个测试客户端测试中继功能 要测试完整的中继功能,你需要运行两个客户端实例来模拟…...
MCP 自定义python实现server服务,支持离线调用和远程接口访问形式
参考: https://blog.csdn.net/lingding_cn/article/details/147355620 其他百炼、mcp服务网址支持链接访问 server服务代码: 出行酒店查询 mcp server代码编写参考:https://blog.csdn.net/weixin_42357472/article/details/146503660 api_mcp_server.py import pickle im…...
搭建PCDN大节点,服务器该怎么配
搭建P2P大节点时,服务器要怎么配呢?需要综合考虑硬件性能、网络带宽、存储能力、系统架构以及安全性等多个方面,以确保节点能够高效、稳定地运行。 一、硬件配置 CPU:选择高性能的多核处理器,以满足高并发处理需求。核…...
JavaScript的3D库有哪些?
JavaScript的3D库有哪些? 在3D开发领域,JavaScript提供了多种库和框架,使开发者能够在浏览器中创建丰富的3D体验。以下是一些流行的3D方面的JavaScript库: Three.js:这是最著名的用于创建3D图形的JavaScript库之一。它…...
如何解决matlab/octave画图legend图例颜色一样的问题?
预期目的: 本意想用legend在画图的时候把对应线段的颜色对应起来,实际按照如下代码运行得不到预期的结果。 x [1:10;11:20]y1 x.^2;y2 0.5.*x.^3plot(x,y1,r,x,y2,b);legend(y x^2,y x^3) 代码运行结果如下: 原因 是matlab /octave默…...
[第十五章][15.3.2 shellcode注入攻击]ret2shellcode+[NewStarCTF 公开赛赛道]ret2shellcode
1、[NewStarCTF 公开赛赛道]ret2shellcode IDA 反编译看伪代码: buf mmap((void *)0x233000, 0x1000uLL, 7, 34, -1, 0LL); 这里直接给了 buf 7 的权限,即可读可写可执行,那么 shellcode 肯定写到 buf 里 buf 的映射地址:0x23…...
边缘计算:数字世界的”末梢神经系统”解析-优雅草卓伊凡
边缘计算:数字世界的”末梢神经系统”解析-优雅草卓伊凡 一、边缘计算深度解析 1.1 边缘计算的定义与架构 边缘计算(Edge Computing)是一种分布式计算范式,它将数据处理能力从传统的集中式云数据中心推向网络边缘,更…...
基于CATIA参数化球体建模的自动化插件开发实践——NX建模之球体命令的参考与移植
引言 在CATIA二次开发领域,Python因其灵活性和丰富的库支持逐渐成为高效工具开发的首选语言。本文将以笔者开发的CATIA球体自动化建模工具为例,参考NX软件中高效球体创建命令,深度解析基于PySide6 GUI框架与pycatia接口库的集成…...
ActiveMQ 可靠性保障:消息确认与重发机制(一)
引言 在当今分布式系统的架构中,消息中间件扮演着举足轻重的角色,而 ActiveMQ 作为一款广泛使用的开源消息中间件,凭借其对 JMS(Java Message Service)规范的支持、多种消息传输协议、丰富的消息模型(如点对…...
麒麟、UOS系统在线打开word文件并提取修订痕迹
麒麟、UOS系统在线打开word文件并提取修订痕迹 查看本示例演示效果(Windows版) 查看本示例演示效果(国产版)本示例关键代码的编写位置,请参考“开始 - 快速上手”里您所使用的开发语言框架的最简集成代码 注意 本文中…...
Vue3笔记摘录
1.Vue3整体知识概览图 2.ref与reactive具体使用区别 2-1 基本类型处理 const count1 ref(0) 使用ref自动转化为数字类型const count2 reactive(0) 参数必须是对象类型 2-2 具体使用过程 // ref 处理对象(自动解包) const user ref({name: John,a…...
大力探索“AI·Life爱生活”项目峰会暨战略投资签约仪式成功举办
2025年4月26日,杭州西溪雷迪森大酒店内气氛热烈非凡,大力探索(杭州)科技有限公司主办的“大力探索项目峰会暨战略投资签约仪式”在此隆重开启。这场汇聚了数百位行业精英与企业代表的盛会,不仅是一场智慧的碰撞&#x…...
复刻低成本机械臂 SO-ARM100 材料齐活篇
视频讲解: 复刻低成本机械臂 SO-ARM100 材料齐活篇 打印件基本ok,总共12个,尴尬的是github又更新了so-101,不过看了下还好只是优化了走线和几个结构键,影响不大,大不了后面再重新打印(有3d打印机…...
解读 AI绘画工作流ComfyUI Stable Diffusion
ComfyUI 是什么?图像工作流又是什么? 认识ComfyUI 从名词术语来看: ComfyUI是一个基于节点流程的Stable Diffusion操作界面,通过自定义节点、拖拽连线实现精准的工作流定制,以完成更复杂的图像生成工作。 </...
北极星 新美团核销接口对接
美团吃相难看,东哥就应该干掉他 申请官方接口一般来说很难了 现在无非就是几种第三方开放出来的接口 按量收费,但是需要一次性充钱收首期的技术服务费 ,然后按年收费就是我们技术自己解决的方式,方便便宜 ,代码齐全,…...
理解数据库存储以及查询(集合)
理解数据库存储以及查询(集合) 基本概念定义 主键集合: 定义:主键集合是由数据库表中的主键组成的一个集合。主键是表中唯一标识每一行记录的属性(或属性组合)。 特性:主键集合包含表的主键属性…...
(Go Gin)Gin学习笔记(四)Gin的数据渲染和中间件的使用:数据渲染、返回JSON、浅.JSON()源码、中间件、Next()方法
1. 数据渲染 1.1 各种数据格式的响应 json、结构体、XML、YAML类似于java的properties、ProtoBuf 1.1.1 返回JSON package mainimport ("github.com/gin-gonic/gin""net/http" )func main() {r : gin.Default()r.POST("/demo", func(res *gi…...
机器视觉橡胶制品检测的应用
橡胶制品在生产过程中易出现划痕、气泡、缺料、毛边、杂质嵌入等多种缺陷,这些缺陷往往微小且随机分布,人工检测不仅耗时,漏检率也居高不下。尤其在汽车密封件、医疗硅胶制品等高端领域,微米级的缺陷都可能导致产品失效࿰…...
JavaScript:从JS的执行机制到location对象
一、JS执行机制 (1)JS是单线程 JavaScript语言的一大特点就是单线程,也就是同一时间只能做一件事。因为JavaScript是为了处理页面中的用户交互,以及制作DOM二诞生的。比如我们对某个DOM元素进行添加和删除操作,这个不…...
Sigmoid函数简介及其Python实现
文章目录 一、Sigmoid 函数简介1. 数学公式2. 关键特性3. 应用场景 二、Python 实现1. 使用 math 库 (适用于单个数值)2. 使用 numpy 库 (适用于数值、列表、数组、矩阵)3. 使用 scipy.special.expit (数值稳定) 三、小结 一、Sigmoid 函数简介 Sigmoid 函数(也称为…...
全局事件总线EventBus的用法
全局事件总线 EventBus 在前端开发中是一种用于实现组件间通信的机制,适用于兄弟组件或跨层级组件间的数据传递。 1. 创建全局 EventBus 实例 在前端项目中,先创建一个全局的 EventBus 实例。在 Vue 中,可以通过创建一个新的 Vue 实例来实现…...
嵌入式Linux系统中的线程信号处理:策略与实践
在嵌入式Linux系统的开发中,多线程编程是提升系统性能和响应速度的重要手段。然而,多线程环境下的信号处理却是一个复杂且需要细致处理的问题。信号,作为进程间通信的一种机制,在嵌入式系统中常用于处理外部事件或中断。但在多线程…...
CCM/TCM在STM32中的含义和用途
CCM/TCM在STM32中的含义和用途 CCM(Core Coupled Memory)和TCM(Tightly Coupled Memory)是ARM架构中的特殊内存类型,它们都表示与CPU核心紧密耦合的内存区域。这些内存具有一些特殊特性,使其在某些应用场景…...