【Spring】事务
在软件开发中,事务确保一组操作要么全部成功,要么全部失败,这对于数据库操作尤为重要,因为任何单一操作的失败都可能导致数据不一致。Spring 事务管理通过 @Transactional
注解实现,能够轻松地在数据层和业务层维护数据的一致性和完整性。在操作失败时,系统会自动回滚,简化了复杂业务逻辑的处理。接下来,通过一个案例来说明事务的作用。
银行转账案例
在银行转账案例中,我们需要实现任意两个账户之间的转账操作。以账户 Alice 向账户 Bob 转账为例,基于 Spring 和 MyBatis 的整合环境,我们将数据层提供的基础操作用于处理账户余额:减钱(outMoney)和加钱(inMoney)。业务层的 transfer 方法将调用这两个操作,接受两个账号和转账金额作为参数,从而完成转账的模拟。
(1)Spring 整合 MyBatis 项目创建
要搭建基于 Spring 整合 MyBatis 环境,可参考《Spring 整合 MyBatis》,也可以直接使用以下代码。
- 项目目录
- com.it.config.JdbcConfig
package com.it.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;import javax.sql.DataSource;public class JdbcConfig {@Value("${jdbc.driver}")private String driver;@Value("${jdbc.url}")private String url;@Value("${jdbc.username}")private String userName;@Value("${jdbc.password}")private String password;// 1. 定义一个方法获取要管理的对象// 2. 添加 @Bean,表示当前方法的返回值是一个 Bean@Bean("dataSource")public DataSource dataSource () {DruidDataSource ds = new DruidDataSource();ds.setDriverClassName(driver);ds.setUrl(url);ds.setUsername(userName);ds.setPassword(password);return ds;}
}
- com.it.config.MybatisConfig
package com.it.config;import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;import javax.sql.DataSource;public class MybatisConfig {@Beanpublic SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();ssfb.setDataSource(dataSource);return ssfb;}@Beanpublic MapperScannerConfigurer mapperScannerConfigurer() {MapperScannerConfigurer msc = new MapperScannerConfigurer();msc.setBasePackage("com.it.dao");return msc;}
}
- com.it.config.SpringConfig
package com.it.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;@Configuration
@ComponentScan("com.it")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MybatisConfig.class})
public class SpringConfig {
}
- com.it.dao.AccountDao
package com.it.dao;import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;public interface AccountDao {@Update("update accounts set money = money + #{money} where name = #{name}")void inMoney(@Param("name") String name, @Param("money") Double Money);@Update("update accounts set money = money - #{money} where name = #{name}")void outMoney(@Param("name") String name, @Param("money") Double Money);
}
- com.it.domain.Account
package com.it.domain;public class Account {private Integer id;private String name;private Double money;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Double getMoney() {return money;}public void setMoney(Double money) {this.money = money;}@Overridepublic String toString() {return "Account{" +"id=" + id +", name='" + name + '\'' +", money=" + money +'}';}
}
- com.it.service.impl.AccountServiceImpl
package com.it.service.impl;import com.it.dao.AccountDao;
import com.it.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;public void transfer(String out, String in, Double money) {accountDao.outMoney(out, money);accountDao.inMoney(in, money);}
}
- com.it.service.AccountService
package com.it.service;public interface AccountService {/**** @param out 转出方* @param in 转入方* @param money 金额*/public void transfer(String out, String in, Double money);
}
- resources/jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///db?useSSL=false
jdbc.username=root
jdbc.password=123456
- test/java/com.it.service.AccountServiceTest
package com.it.service;import com.it.config.SpringConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.io.IOException;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {@Autowiredprivate AccountService accountService;@Testpublic void testTransfer() throws IOException {accountService.transfer("Alice", "Bob", 100D);}
}
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.it</groupId><artifactId>spring_tx</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><!-- Spring 依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version></dependency><!-- MyBatis 依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency><!-- MySQL 依赖 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency><!-- Spring JDBC 依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.10.RELEASE</version></dependency><!-- Spring 整合 MyBatis 依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.0</version></dependency><!-- Druid 连接池依赖 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version></dependency><!-- junit 依赖 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><!-- Spring Test 依赖 --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.2.10.RELEASE</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>RELEASE</version><scope>test</scope></dependency></dependencies>
</project>
(2)创建数据表
使用 MySQL 数据库,创建名为 db
的数据库。在 db
中创建 accounts
表,向表中添加 Alice
和 Bob
两个模拟账户,每个账户初始金额设置为 1000
:
create table accounts
(id int auto_incrementprimary key,name varchar(100) not null,money double default 0 null
);INSERT INTO db.accounts (id, name, money) VALUES (1, 'Alice', 1000);
INSERT INTO db.accounts (id, name, money) VALUES (2, 'Bob', 1000);
(3)创建账户间的转账事务
下面这段代码实现了 Alice 向 Bob 转账 100 的操作,并且插入了 1/0
异常代码。在运行 AccountServiceTest 类中的 testTransfer 方法时,如果不存在 1/0
异常代码,则代码正常执行,Alice 的账户减少 100,Bob 的账户增加 100。然而,由于插入了 1/0
异常代码,导致整体业务失败。这个过程中,尽管异常前的操作成功,异常后的操作却失败,这意味着转账业务无法完成。
@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;public void transfer(String out, String in, Double money) {accountDao.outMoney(out, money);int i = 1/0; // 异常处accountDao.inMoney(in, money);}
}
为了解决上述问题,我们需要在业务层实现事务的完整性,这要求开启 Spring 的事务管理。首先,在需要开启事务的方法上添加 @Transactional
注解,通常建议将其添加在接口上,而不是具体的实现类上:
public interface AccountService {/**** @param out 转出方* @param in 转入方* @param money 金额*/@Transactionalpublic void transfer(String out, String in, Double money);
}
接着,在 JdbcConfig 类中配置事务管理器:
@Bean
public PlatformTransactionManager transactionManager (DataSource dataSource) {DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();transactionManager.setDataSource(dataSource);return transactionManager;
}
最后,在 SpringConfig 中告知 Spring 使用事务驱动:
@Configuration
@ComponentScan("com.it")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class, MybatisConfig.class})
@EnableTransactionManagement // 添加这一行注解
public class SpringConfig {
}
在完成事务开启后,AccountServiceImpl 类的 transfer 方法中的两个数据操作要么全部成功,要么全部失败。如果在两者之间发生异常,Spring 将会回滚事务,确保两个操作都失败,而不会出现一个成功、一个失败的情况。
(4)事务管理步骤小结
- 在业务层接口上添加 Spring 事务管理(
@Transactional
注解) - 设置事务管理器(PlatformTransactionManager)
- 开启注解式事务驱动(
@EnableTransactionManagement
注解)
Spring 注解式事务通常添加在业务层接口中而不会添加到业务层实现类中,降低耦合。另外,注解式事务可以添加到业务方法上表示当前方法开启事务,也可以添加到接口上表示当前接口所有方法开启事务。
事务角色
在银行转账案例中,业务层的 transfer 方法调用了数据层的两个操作:outMoney 和 inMoney。这两个操作独立执行,通常需要开启两个不同的事务,记为 T1 和 T2,因此它们之间的回滚互不影响。这就导致了在操作异常时,无法实现要么全部成功,要么全部失败的效果。
Spring 事务通过 @Transactional 注解来解决这个问题。当业务层方法开启事务 T 时,数据层的 T1 和 T2 被纳入事务 T 的管理范围。这样,代码中实际上只有一个完整的事务 T,从而确保两个数据层操作的同成功和同失败。在这个过程中,有两个事务角色:
- 事务管理员:发起事务的业务层方法,通常指代开启事务的地方
- 事务协调员:参与事务的数据层方法,负责执行具体操作
事务属性
Spring 事务的属性如下所示。其中,两个较为重要且难以理解的属性是 rollbackFor 和 propagation。
(1)rollbackFor 属性
rollbackFor 属性的作用是设置事务的回滚异常。在 Spring 的事务管理中,并不是所有异常的出现后,Spring 事务都会发生回滚。有些异常不会,比如 IOException 异常:
@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;public void transfer(String out, String in, Double money) throws IOException{accountDao.outMoney(out, money);
// int i = 1/0;if (true) {throw new IOException();}accountDao.inMoney(in, money);}
}
因此,需要为这类事务单独设置异常回滚,在 rollbackFor 属性中指定 IOException :
public interface AccountService {/**** @param out 转出方* @param in 转入方* @param money 金额*/@Transactional(rollbackFor = {IOException.class})public void transfer(String out, String in, Double money) throws IOException;
}
(2)propagation 属性
为了说明 propagation 属性的作用,在转账业务代码基础上添加日志记录功能。具体而言,无论转账是否成功,每次转账操作都应在数据库中留痕。为此,首先在数据库中添加 logs 表:
create table logs
(id int auto_incrementprimary key,message varchar(512) not null,create_date date null
);
接着,实现 LogDao 接口,提供向 logs 表添加记录的功能:
package com.it.dao;import org.apache.ibatis.annotations.Insert;public interface LogDao {@Insert("insert into logs (message,create_date) values(#{message},now())")void log(String message);
}
之后,实现日志模块的业务层:
package com.it.service;import org.springframework.transaction.annotation.Transactional;public interface LogService {@Transactionalvoid log(String out, String in, Double money);
}
package com.it.service.impl;import com.it.dao.LogDao;
import com.it.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;@Service
public class LogServiceImpl implements LogService {@Autowiredprivate LogDao logDao;@Overridepublic void log(String out, String in, Double money) {logDao.log("From " + out + " to " + in + ", money: " + "money");}
}
最后,在 AccountServiceImpl 的 transfer 方法中添加日志模块,将添加日志的操作放在 finally 代码块中,原因是希望无论 try 代码块中的代码是否正常执行,最终都添加日志记录。
@Service
public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountDao accountDao;@Autowiredprivate LogService logService;public void transfer(String out, String in, Double money){try {accountDao.outMoney(out, money);accountDao.inMoney(in, money);} finally {logService.log(out, in, money);}}
}
运行代码后,执行正常。现在在 try 代码块中添加异常,并再次执行:
try {accountDao.outMoney(out, money);int i = 1/0;accountDao.inMoney(in, money);
} finally {logService.log(out, in, money);
}
此时,accounts
表中的数据未发生变化,且 logs 表中也没有任何日志记录。这表明日志记录与转账操作属于同一个事务(如上图所示),结果要么成功,要么失败。显然,这不是我们预期的结果。我们希望无论转账操作是否失败,都能将日志记录到数据库中。为此,需要引入事务传播行为的概念:
事务传播行为:事务协调员对事务管理员所携带事务的处理态度。
分析可知,上述现象是由于日志模块的事务协调员选择加入转账操作的事务。为了解决这个问题,可以设置日志模块单独开启一个新事务,而不加入转账事务。这一需求可以通过配置 propagation 属性来实现:
public interface LogService {@Transactional(propagation = Propagation.REQUIRES_NEW)void log(String out, String in, Double money);
}
代码中的 Propagation.REQUIRES_NEW
指定了需要一个新事务,从而满足了日志记录的需求。以下是事务传播行为及 propagation 属性的所有情况和取值:
相关文章:
【Spring】事务
在软件开发中,事务确保一组操作要么全部成功,要么全部失败,这对于数据库操作尤为重要,因为任何单一操作的失败都可能导致数据不一致。Spring 事务管理通过 Transactional 注解实现,能够轻松地在数据层和业务层维护数据…...
canvas+fabric实现时间刻度尺(二)
前言 我们前面实现了时间刻度尺,鼠标移动显示时间,接下来我们实现鼠标点击某个时间进行弹框。 效果 实现 1.监听鼠标按下事件 2.编写弹框页面 3.时间转换 <template><div><canvas id"rulerCanvas" width"1200"…...
IPv6的过度技术
如何界定手动与自动? 主要是隧道目标地址能否自动获取 👯1. 双栈 必须支持IPv4和IPv6协议 链接双栈网络的接口必须同时配置v4和v6地址 路由器能够根据二层标记识别协议,type:0x0800代表IPV4,type:0x…...
介绍 Apache Spark 的基本概念和在大数据分析中的应用。
Apache Spark是一个开源的大数据处理框架,可用于高速处理和分析大规模数据集。它可以在分布式集群上运行,并且具有内存计算的能力,因此可以比传统的批处理框架更快地处理数据。 在Spark中,数据被表示为弹性分布式数据集ÿ…...
VA01/VA02检查增强
VA01/VA02检查增强 一、增强描述 VA01/VA02创建或修改SO时候,在点击“保存”按钮的节点,客户需求对一些约束条件进行检查,此处以 SO行项目对应的“利润中心”字段必输为例。通过查询更多的增强:SPRO–销售和分销–系统修正–用户…...
基于SpringBoot和Leaflet的全球机场空间分布可视化实战
目录 前言 一、航空机场的空间模型 1、空间表简介 2、数据查询 二、机场WebGIS空间分布可视化 1、后台数据查询 2、Leaflet页面开发 三、WebGIS分析 1、全球航空格局 2、我国机场影像 四、总结 前言 时光轻轻挥别2024,来到了2025年。在崭新的2025年里&am…...
FPGA交通灯实现
1 原理 FPGA(现场可编程门阵列)交通灯实现原理主要是基于硬件描述语言(如VHDL或Verilog)编程,通过FPGA内部的逻辑单元和寄存器来实现交通灯的控制功能。以下是对FPGA交通灯实现原理的详细解释: 一、交通灯的基本功能 交通灯的主要功能包括红灯、黄灯和绿灯的显示,以及…...
厦门大学联合网易提出StoryWeaver,可根据统一模型内给定的角色实现高质量的故事可视化
厦门大学联合网易提出StoryWeaver,可以根据统一模型内给定的角色实现高质量的故事可视化。可根据故事文本生成与之匹配的图像,并且确保每个角色在不同的场景中保持一致。本文的方法主要包括以下几个步骤: 角色图构建:设计一个角色…...
【Rust自学】8.1. Vector
喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 8.1.0. 本章内容 第八章主要讲的是Rust中常见的集合。Rust中提供了很多集合类型的数据结构&…...
华为OD机试真题---服务器广播
华为OD机试中的“服务器广播”题目是一个经典的算法问题,通常涉及图论和连通分量的概念。以下是对该题目的详细解析: 一、题目描述 服务器之间可以通过网络进行连接,连接方式包括直接相连和间接连接。给出一个NN的数组(矩阵&…...
又一年。。。。。。
2024,浑浑噩噩的一年。 除了100以内的加减法(数据,数据,还是数据。。。。。。),似乎没做些什么。 脸盲症越来越重的,怕是哪天连自己都不认得自己的了。 看到什么,听到什…...
【JAVA高级篇教学】第六篇:Springboot实现WebSocket
在 Spring Boot 中对接 WebSocket 是一个常见的场景,通常用于实现实时通信。以下是一个完整的 WebSocket 集成步骤,包括服务端和客户端的实现。本期做个简单的测试用例。 目录 一、WebSocket 简介 1. 什么是 WebSocket? 2. WebSocket 的特…...
Kotlin在医疗大健康域的应用实例探究与编程剖析(下)
四、Kotlin医疗编程实例分析 4.1 移动医疗应用实例 4.1.1 患者健康监测应用 在当今数字化医疗时代,患者健康监测应用为人们提供了便捷的健康管理方式。利用Kotlin开发的患者健康监测应用,能够实时采集患者的各类生理数据,如心率、血压、血氧饱和度等,并通过直观的可视化…...
Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(3):配置备用数据库
Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(3):配置备用数据库 目录 Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(3):配置备用数据库一、…...
LeetCode算法题——移除元素
题目描述 给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作࿱…...
七大设计原则之开闭原则
目录 一、什么是开闭原则? 二、如何做到开闭原则? 1、面向接口或抽象类编程 2、依赖注入 3、单一职责原则 三、是不是为了满足开闭原则就要一味的追求代码的扩展性? 一、什么是开闭原则? 相信很多人都听说过这个原则&#x…...
【stm32+K210项目】基于K210与STM32协同工作的智能垃圾分类系统设计与实现(完整工程资料源码)
视频效果演示: 基于K210与STM32协同工作的智能垃圾分类系统设计与实现 目录: 目录 视频效果演示: 目录: 项目简介: 一、设计目的: 1.1 项目背景 1.2 设计意义: 二、硬件部分: 2.1 st…...
Ps:创建数据驱动的图像
在设计实践中,常常需要处理大量内容变化但设计格式统一的任务,例如批量生成名片、工作证、学生证、胸牌、奖状或证书甚至图册。这些工作如果逐一手动制作,不仅耗时费力,还容易出错。 为解决这一问题,Photoshop 提供了强…...
git的全通路线介绍
一、关系 1.git是代码版本管理工具,即可将项目切换到任意版本。 2.github与gitee是基于git技术构建的远程仓库网站。github是国外建立的,资源更丰富;gitee是国内建立的,免费功能更多。 3.gitlab与github类似,只不过…...
R1-3学习打卡
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 RNN心脏病识别 导入数据数据预处理标准化模型训练模型评估个人总结 import tensorflow as tfgpus tf.config.list_physical_devices("GPU")…...
Vue.js组件开发-实现无感刷新Token
在Vue.js应用中,实现无感刷新Token涉及到在用户的会话Token即将过期或已经过期时自动获取新的Token,而不影响用户的操作体验。需要通过拦截器(interceptors)来处理API请求,并在检测到Token过期或无效时自动进行刷新。 …...
可编辑31页PPT | 大数据湖仓一体解决方案
荐言分享:在当今数字化时代,大数据已成为企业决策和业务优化的关键驱动力。然而,传统的数据处理架构,如数据仓库和数据湖,各自存在局限性,难以满足企业对数据高效存储、灵活处理及实时分析的综合需求。因此…...
如何实现一个充满科技感的官网(二)
背景 在上一篇文章 《如何实现一个充满科技感的官网(一)》 中,我们初步了解了该官网的整体设计,并与大家探讨了它的视觉呈现和用户体验。 我们前期的内部设计偏向简洁,所以开始思考如何提升网站的整体设计感。这些尝…...
深度学习算法:从基础到实践
简介 深度学习作为人工智能领域的一个重要分支,近年来在多个领域取得了显著的成就。本文将从基础概念出发,探讨深度学习算法的核心原理,并介绍一些实际应用案例。 深度学习算法的核心概念 深度学习算法基于人工神经网络,通过构…...
等价和划分
例子:学生分组 假设我们有一个班级,班级里有10名学生,我们想要根据他们的年龄来分组。我们可以定义一个关系 ( R ) 在学生集合 ( A ) 上,其中 ( A {s_1, s_2, …, s_{10}} ),并且 ( s_i ) 和 ( s_j ) 之间有关系 ( R…...
电商项目-数据同步解决方案(三)商品上架同步更新ES索引库
一、 需求分析和业务逻辑 主要应用技术有:Feign远程调用, 消息队列-RabbitMQ ,分布式搜索引擎-ElasticSearch,Eureka,Canal 商品上架将商品的sku列表导入或者更新索引库。 数据监控微服务需要定义canal监听器&#x…...
MySQL数据库笔记——多版本并发控制MVCC
大家好,这里是Good Note,关注 公主号:Goodnote,本文详细介绍MySQL的并发控制:多版本并发控制MVCC。 文章目录 背景介绍数据库并发控制——锁机制悲观锁和乐观锁悲观锁乐观锁 数据库并发控制——MVCC 的引入MVCC 和锁机…...
【LLM综述】29种大模型Prompt Engineering技术
note 从零样本(Zero-shot)提示到最新进展的各种提示技术,包括推理和逻辑链(Chain-of-Thought, CoT)提示、自动链式思考(Auto-CoT)提示、自我一致性(Self-Consistency)提…...
MySQL高级关联查询与复杂关系的处理
在关系型数据库的操作中,复杂关联查询和多层次关系建模是非常重要的技能。无论是在数据分析、业务数据处理,还是在数据可视化等各个方面,处理多表数据关联都是不可或缺的部分。通过高效的关联查询,可以在不同表之间建立关系,查询并整合多张表的数据,避免数据冗余并提升查…...
URL Moniker API
1. urlmon 介绍 urlmon 是指 URL Moniker API,它是 Microsoft Windows 操作系统中的一部分,通常用于处理 URL 和相关的任务。urlmon.dll 是其动态链接库,提供了一系列函数和接口,主要用于以下目的: URL 分析和处理&a…...
单元测试3.0+ @RunWith(JMockit.class)+mock+Expectations
Jmockit使用笔记_基本功能使用Tested_Injectable_Mocked_Expectations_jmockit.class-CSDN博客 测试框架Jmockit集合junit使用 RunWith(JMockit.class) 写在测试案例类上的注解 Tested 在测试案例中,写在我们要测试的类上面, 一般用实现类 Injectable 在测试案例中声明…...
halcon中图像滤波分为空间域和频域两种方法
均值滤波是一种线性平滑滤波。基本思想是用某像素邻域几个像素的平均值代替此像素原来的灰度值。 高斯滤波是用某像素邻域几个像素的加权平均值代替此像素的原有灰度值。 总结:图像滤波分为空间域和频域两种方法。 空间域滤波主要是对像素的直接处理,它将…...
maxminddb地理信息库–C语言
原文地址:maxminddb地理信息库–C语言 – 无敌牛 欢迎参观我的个人博客:无敌牛 – 技术/著作/典籍/分享等 maxminddb 是一个 IP 的地理信息库,可以根据 IP 地址给出对应的地理位置信息。 下载离线库 maxminddb提供在线查询,也…...
Keil中的gcc
文章目录 一、IDE背后的命令1.1 IDE是什么1.2 IDE的背后是命令1.3 有两套主要的编译器 二、准备工作2.1 arm-linux-gcc和gcc是类似的2.2 Code::Blocks2.2.1 设置windows环境变量2.2.2 命令行示例 三、gcc编译过程详解3.1 程序编译4步骤3.2 gcc的使用方法3.2.1 gcc使用示例3.2.2…...
【Java数据结构】栈和队列相关算法
第一题:改变元素的序列 例1:若进栈序列为1,2,3,4,进栈过程中可以出栈,则下列不可能一个出栈序列(); A:1,4,3,…...
LoRA微调系列笔记
系列文章目录 第一章:LoRA微调系列笔记 第二章:Llama系列关键知识总结 第三章:LLaVA模型讲解与总结 文章目录 系列文章目录LoRA:Low-Rank Adaptation of Large Language Models目的:依据:优势:…...
Linux(Ubuntu)下ESP-IDF下载与安装完整流程(3)
接前一篇文章:Linux(Ubuntu)下ESP-IDF下载与安装完整流程(2) 本文主要看参考官网说明,如下: 快速入门 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档 Linux 和 macOS 平台工具链的标准设置 - ESP32-S3 - — ESP-IDF 编程指南 latest 文档 一、安装准备 1. Linux用...
【C++】22___STL常用算法
目录 一、常用遍历算法 二、常用查找算法 2.1 find 2.2 其它查找算法 三、常用排序算法 3.1 sort 3.2 其它排序算法 四、拷贝 & 替换 4.1 copy 4.2 其它算法 五、常用的算数生成算法 5.1 accumulate 5.2 fill 六、常用集合算法 6.1 set_intersection 6…...
linux 批量替换文件指定字符串
启发:数据库连接串的用户名需要从sa修改为sasa find . -type f -name mssql.json -exec sed -i s/IDsa;/IDsasa;/g {}...
List接口(源码阅读)
文章目录 1.List接口常用方法1.代码2.结果 2.ArrayList底层机制1.结论2.ArrayList底层源码1.代码2.debug添加第一个元素1.进入2.elementData数组存储ArrayList的数据3.初始化为空数组4.首先确保使用size1来计算最小容量5.如果elementData为空,最小容量就是106.modCo…...
股市学习 seekingalpha tradingview
EMA EMA(Exponential Moving Average)是一种技术分析中常用的指标,用于平滑股价或其他资产价格的波动,以帮助分析价格走势的趋势和方向。EMA与简单移动平均(SMA)类似,但对最新价格的权重更大&a…...
用再生龙备份和还原操作系统(三)
续上篇《用再生龙备份和还原操作系统(二)》 三,用再生龙将镜像文件还原到硬盘 将再生龙工具盘、待还原系统的硬盘(与源盘一样大或更大)、镜像文件所在磁盘(如果是U盘,也可以后插)安…...
FaceFusion 从0开始本地部署,RTX4060
FaceFusion 从0开始本地部署指南 一、环境准备 1. 基础工具安装 1.1 Git 安装 使用管理员权限打开 PowerShell执行安装命令: winget install -e --id Git.Git验证安装: git --version1.2 FFmpeg 安装 使用管理员权限打开 PowerShell执行安装命令&…...
Swift Combine 学习(六):自定义 Publisher 和 Subscriber
Swift Combine 学习(一):Combine 初印象Swift Combine 学习(二):发布者 PublisherSwift Combine 学习(三):Subscription和 SubscriberSwift Combine 学习(四&…...
服务器网卡绑定mode和交换机的对应关系
互联网各领域资料分享专区(不定期更新): Sheet 模式类别 网卡绑定mode共有七种(0~6): bond0、bond1、bond2、bond3、bond4、bond5、bond6 mode详解 mode0 ,即:(balance-rr) Round-robin policy(平衡轮循环策略,需要配置交换机静态聚合) mode…...
【动手学轨迹预测】2.4 考虑地图拓扑关系的表征方法
上一节我们介绍了VectorNet提出了矢量化场景表征方法, 大幅提高了预测网络编码性能. 但是VectorNet对地图数据的编码是基于无向无权图的, 并没有考虑到地图的拓扑关系. 显然在预测中, 地图的拓扑关系应该被考虑到. 于是在VectorNet的基础上, LaneGCN提出一种将地图车道作为节点…...
ChatGLM3模型搭建(踩坑记录版)
参考 魔搭社区 https://zhuanlan.zhihu.com/p/720148240 智谱AI通用大模型:本地部署ChatGLM3-6B开源大模型 - 编程库 说明 搭建方式多篇文章结合着看; 模型下载强烈推荐魔塔社区下载ZhipuAI/chatglm3-6b; 官方github指定清华的模型没有…...
基于 Python Django 的花卉商城系统的研究与实现
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...
Spring Boot 3 文件下载、多文件下载以及大文件分片下载、文件流处理、批量操作 和 分片技术
在 Spring Boot 3 中,实现文件下载、多文件下载以及大文件分片下载需要结合以下功能:文件流处理、批量操作 和 分片技术。以下是详细实现方案: 1. 单文件下载 基础的单文件下载实现,可以参考以下代码: GetMapping(&…...
什么是事件循环(Event Loop)?请谈谈它在 JavaScript 中的作用?
事件循环(Event Loop)是什么? 事件循环(Event Loop)是JavaScript运行时环境(如浏览器或Node.js)中的一个核心机制,用于处理异步操作和事件。 它负责协调代码的执行、事件的处理、以…...