Spring Boot中处理简单的事务
说到事务,我们第一影响应该是数据库管理系统的一个重要概念。
事务(Transaction)是数据库管理系统(DBMS)中的一个概念,用于管理对数据库的一组操作,这些操作要么全部成功执行,要么全部回滚(撤销)。
事务通常由一系列数据库操作组成,例如插入、更新、删除等。这些操作被视为一个逻辑上的单元,要么全部执行成功,要么全部不执行。事务具有以下四个特性,通常被称为 ACID 特性:
- 原子性(Atomicity):事务被视为一个不可分割的原子操作,要么全部执行成功,要么全部回滚。如果事务中的任何一个操作失败,整个事务将被回滚到初始状态,数据库不会受到部分操作的影响。
- 一致性(Consistency):事务在执行前和执行后,数据库的完整性约束没有被破坏。这意味着事务必须确保数据库从一个一致的状态转换到另一个一致的状态。
- 隔离性(Isolation):并发执行的多个事务之间应该相互隔离,每个事务的操作应该与其他事务的操作相互独立。隔离性确保了每个事务在并发执行时不会相互干扰,避免了数据的不一致性。
- 持久性(Durability):一旦事务提交成功,其所做的修改将永久保存在数据库中,即使系统发生故障或重启,修改的数据也不会丢失。
事务的使用可以确保数据库操作的一致性和可靠性,尤其在并发访问数据库的环境中,事务的隔离性能够避免数据冲突和并发问题。
那么我们在Spring Boot中如果实现对简单事务的处理呢?
那就随我一同来通过Spring Boot来简单实现一个事务吧:
引入相关依赖:
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>
在Spring Boot的相关配置文件中配置数据库:
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.datasource.primary.username=root
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.hibernate.ddl-auto=create
@Entity
//@Data
//@NoArgsConstructor
public class User {@Id@GeneratedValueprivate Long id;private String name;@Max(50)private Integer age;public User(String name, Integer age) {this.name = name;this.age = age;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public User() {}
}
创建一个承载SQL的接口:
public interface UserRepository extends JpaRepository<User, Long> {User findByName(String name);User findByNameAndAge(String name, Integer age);@Query("from User u where u.name=:name")User findUser(@Param("name") String name);}
最后创建一个测试类:
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTests {@Autowiredprivate UserRepository userRepository;@Test//@Transactional //这个注解先不加执行,再一次执行的时候加然后看结果。public void test() throws Exception {// 创建10条记录userRepository.save(new User("AAA", 10));userRepository.save(new User("BBB", 20));userRepository.save(new User("CCC", 30));userRepository.save(new User("DDD", 40));userRepository.save(new User("EEE", 50));userRepository.save(new User("FFF", 60));userRepository.save(new User("GGG", 70));userRepository.save(new User("HHH", 80));userRepository.save(new User("III", 90));userRepository.save(new User("JJJ", 100));// 测试findAll, 查询所有记录Assert.assertEquals(10, userRepository.findAll().size());// 测试findByName, 查询姓名为FFF的UserAssert.assertEquals(60, userRepository.findByName("FFF").getAge().longValue());// 测试findUser, 查询姓名为FFF的UserAssert.assertEquals(60, userRepository.findUser("FFF").getAge().longValue());// 测试findByNameAndAge, 查询姓名为FFF并且年龄为60的UserAssert.assertEquals("FFF", userRepository.findByNameAndAge("FFF", 60).getName());// 测试删除姓名为AAA的UseruserRepository.delete(userRepository.findByName("AAA"));// 测试findAll, 查询所有记录, 验证上面的删除是否成功Assert.assertEquals(9, userRepository.findAll().size());}}
因为我们在实体类中通过@Max
注解为User的age设置了最大值为50,这样就可以通过创建User实体的age属性超过50的时候就可以触发异常,也就是我在上边测试类的执行年龄大于50岁的数据都会被终止:
HHH000346: Error during managed flush [Validation failed for classes [com.miaow.demo.User] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[ConstraintViolationImpl{interpolatedMessage='最大不能超过50', propertyPath=age, rootBeanClass=class com.miaow.demo.User, messageTemplate='{javax.validation.constraints.Max.message}'}
]]
如果我们去查数据库表会发现只存在包含50岁以下的所有数据,其他数据就添加失败了。
这个时候我们就需要进行事务处理了,因为他插入了50岁以前的,但是50岁以后的都没了,这样就不满足事务的原子性了,要么都做要么都不做,我们可以通过@Transactional
来实现,之后我们在瞅瞅数据库表中数据,我们发现在没加@Transactional
的时候,他会执行一部分,另一部分不执行,也就是不满足我们事务中的原子性,在我们加了@Transactional
当我们执行收到阻碍的时候,或者被异常终止的时候,会使用@Rollback注解让我们的相关类都可以在结束的时候得到回滚,也就是,这件事情,要么做,要做就要做成功,要么不做。
事务的隔离级别
说到了事务,那么我们需要提及的是隔离级别,事务的隔离级别是我们的数据库管理系统中用来控制并访问数据的一种机制,他定义了事务在同时访问数据库的时候,对其他事务的影响程度和可以见性的一种规则。
我们常见的隔离级别:
- 读未提交(Read Uncommitted):最低的隔离级别,允许一个事务读取另一个事务未提交的数据。可能会导致脏读(Dirty Read)问题。
- 读已提交(Read Committed):保证一个事务只能读取到已经提交的数据。避免了脏读问题,但可能会导致不可重复读(Non-repeatable Read)问题。
- 可重复读(Repeatable Read):保证一个事务在执行期间多次读取同样的数据时,能够得到一致的结果。避免了不可重复读问题,但可能会导致幻读(Phantom Read)问题。
- 串行化(Serializable):最高的隔离级别,通过强制事务串行执行来避免并发问题。可以避免脏读、不可重复读和幻读问题,但会降低并发性能。
package org.springframework.transaction.annotation;import org.springframework.transaction.TransactionDefinition;/*** Enumeration that represents transaction isolation levels for use* with the {@link Transactional} annotation, corresponding to the* {@link TransactionDefinition} interface.** @author Colin Sampaleanu* @author Juergen Hoeller* @since 1.2*/
public enum Isolation {/*** Use the default isolation level of the underlying datastore.* All other levels correspond to the JDBC isolation levels.* @see java.sql.Connection*/DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),/*** A constant indicating that dirty reads, non-repeatable reads and phantom reads* can occur. This level allows a row changed by one transaction to be read by* another transaction before any changes in that row have been committed* (a "dirty read"). If any of the changes are rolled back, the second* transaction will have retrieved an invalid row.* @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED*/READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),/*** A constant indicating that dirty reads are prevented; non-repeatable reads* and phantom reads can occur. This level only prohibits a transaction* from reading a row with uncommitted changes in it.* @see java.sql.Connection#TRANSACTION_READ_COMMITTED*/READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),/*** A constant indicating that dirty reads and non-repeatable reads are* prevented; phantom reads can occur. This level prohibits a transaction* from reading a row with uncommitted changes in it, and it also prohibits* the situation where one transaction reads a row, a second transaction* alters the row, and the first transaction rereads the row, getting* different values the second time (a "non-repeatable read").* @see java.sql.Connection#TRANSACTION_REPEATABLE_READ*/REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),/*** A constant indicating that dirty reads, non-repeatable reads and phantom* reads are prevented. This level includes the prohibitions in* {@code ISOLATION_REPEATABLE_READ} and further prohibits the situation* where one transaction reads all rows that satisfy a {@code WHERE}* condition, a second transaction inserts a row that satisfies that* {@code WHERE} condition, and the first transaction rereads for the* same condition, retrieving the additional "phantom" row in the second read.* @see java.sql.Connection#TRANSACTION_SERIALIZABLE*/SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);private final int value;Isolation(int value) {this.value = value;}public int value() {return this.value;}
}
针对这个枚举类我们来看一下,我们的Spring Boot的Transaction 中定义的5个表示隔离级别值:
public enum Isolation {DEFAULT(-1),READ_UNCOMMITTED(1),READ_COMMITTED(2),REPEATABLE_READ(4),SERIALIZABLE(8);
}
DEFAULT
:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是:READ_COMMITTED。READ_UNCOMMITTED
:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。READ_COMMITTED
:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。REPEATABLE_READ
:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。SERIALIZABLE
:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
传播行为
所谓的事务传播行为值的是,如果在开始执行当前事务之前,一个事务上下文以及存在,此时若有若干选项可以指定一个事务性方法的执行行为。
package org.springframework.transaction.annotation;import org.springframework.transaction.TransactionDefinition;/*** Enumeration that represents transaction propagation behaviors for use* with the {@link Transactional} annotation, corresponding to the* {@link TransactionDefinition} interface.** @author Colin Sampaleanu* @author Juergen Hoeller* @since 1.2*/
public enum Propagation {/*** Support a current transaction, create a new one if none exists.* Analogous to EJB transaction attribute of the same name.* <p>This is the default setting of a transaction annotation.*/REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),/*** Support a current transaction, execute non-transactionally if none exists.* Analogous to EJB transaction attribute of the same name.* <p>Note: For transaction managers with transaction synchronization,* PROPAGATION_SUPPORTS is slightly different from no transaction at all,* as it defines a transaction scope that synchronization will apply for.* As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)* will be shared for the entire specified scope. Note that this depends on* the actual synchronization configuration of the transaction manager.* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization*/SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),/*** Support a current transaction, throw an exception if none exists.* Analogous to EJB transaction attribute of the same name.*/MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),/*** Create a new transaction, and suspend the current transaction if one exists.* Analogous to the EJB transaction attribute of the same name.* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box* on all transaction managers. This in particular applies to* {@link org.springframework.transaction.jta.JtaTransactionManager},* which requires the {@code javax.transaction.TransactionManager} to be* made available to it (which is server-specific in standard Java EE).* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager*/REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),/*** Execute non-transactionally, suspend the current transaction if one exists.* Analogous to EJB transaction attribute of the same name.* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box* on all transaction managers. This in particular applies to* {@link org.springframework.transaction.jta.JtaTransactionManager},* which requires the {@code javax.transaction.TransactionManager} to be* made available to it (which is server-specific in standard Java EE).* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager*/NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),/*** Execute non-transactionally, throw an exception if a transaction exists.* Analogous to EJB transaction attribute of the same name.*/NEVER(TransactionDefinition.PROPAGATION_NEVER),/*** Execute within a nested transaction if a current transaction exists,* behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB.* <p>Note: Actual creation of a nested transaction will only work on specific* transaction managers. Out of the box, this only applies to the JDBC* DataSourceTransactionManager when working on a JDBC 3.0 driver.* Some JTA providers might support nested transactions as well.* @see org.springframework.jdbc.datasource.DataSourceTransactionManager*/NESTED(TransactionDefinition.PROPAGATION_NESTED);private final int value;Propagation(int value) {this.value = value;}public int value() {return this.value;}}
事务传播行为是指在多个事务之间进行操作时,事务的行为方式。常见的事务传播行为包括:
REQUIRED
:如果当前存在事务,则加入该事务,如果没有事务,则创建一个新的事务。这是默认的传播行为。REQUIRES_NEW
:无论当前是否存在事务,都创建一个新的事务。如果当前存在事务,则将其挂起。SUPPORTS
:如果当前存在事务,则加入该事务,如果没有事务,则以非事务方式执行。NOT_SUPPORTED
:以非事务方式执行操作,如果当前存在事务,则将其挂起。MANDATORY
:如果当前存在事务,则加入该事务,如果没有事务,则抛出异常。NEVER
:以非事务方式执行操作,如果当前存在事务,则抛出异常。NESTED
:如果当前存在事务,则在嵌套事务中执行。嵌套事务是外部事务的一部分,可以独立提交或回滚,但是如果外部事务回滚,则嵌套事务也会回滚。
事务传播行为可以根据具体的业务需求来选择,以确保事务的一致性和可靠性。不同的传播行为可以在多个事务之间提供灵活的控制和管理。
指定方法:通过使用propagation属性设置,例如:
@Transactional(propagation = Propagation.REQUIRED)
相关文章:
Spring Boot中处理简单的事务
说到事务,我们第一影响应该是数据库管理系统的一个重要概念。 事务(Transaction)是数据库管理系统(DBMS)中的一个概念,用于管理对数据库的一组操作,这些操作要么全部成功执行,要么全…...
source activate my_env 和conda activate my_env 有什么区别
source activate my_env 和conda activate my_env 有什么区别 source activate 和 conda activate 是两个不同的命令,用于在Conda环境中激活特定的虚拟环境。它们的区别在于它们分别适用于不同版本的Conda。 source activate: source activate 是在Con…...
机器学习模型超参数优化最常用的5个工具包!
优化超参数始终是确保模型性能最佳的关键任务。通常,网格搜索、随机搜索和贝叶斯优化等技术是主要使用的方法。 今天分享几个常用于模型超参数优化的 Python 工具包,如下所示: scikit-learn:使用在指定参数值上进行的网格搜索或…...

出口美国操作要点汇总│走美国海运拼箱的注意事项│箱讯科技
01服务标准 美国的货物需要细致的服务,货物到港后的服务也是非常重要的。如果在货物到港15天内,如果没有报关行进行(PROCEED),货物就会进入了G.O.仓库,G.O.仓库的收费标准是非常高的。 02代理资格审核 美国航线除了各家船公司&a…...

Gateway网关
Gateway网关 1、网关的位置与作用 官网:Spring Cloud Gateway Geteway是Zuul的替代, Zuul:路由和过滤Zuul最终还是会注册到Eureka Zuul网关采用同步阻塞模式不符合要求。 Spring Cloud Gateway基于Webflux,比较完美地支持异步…...

Python Opencv实践 - 车牌定位(纯练手,存在失败场景,可以继续优化)
使用传统的计算机视觉方法定位图像中的车牌,参考了部分网上的文章,实际定位效果对于我目前使用的网上的图片来说还可以。实测发现对于车身本身是蓝色、或是车牌本身上方有明显边缘的情况这类图片定位效果较差。纯练手项目,仅供参考。代码中im…...

U盘插在电脑上显示要格式化磁盘怎么办
U盘是一种便携式存储设备,广泛应用于各种场合。然而,有时候我们可能会遇到一些问题,比如将U盘插入电脑后显示要格式化磁盘,这通常意味着U盘的分区出现了问题或者U盘的文件系统已经损坏。这种情况下,我们应该如何解决呢…...

Python使用腾讯云SDK实现对象存储(上传文件、创建桶)
文章目录 1. 开通服务2. 创建存储桶3. 手动上传文件并查看4. python上传文件4.1 找到sdk文档4.2 初始化代码4.3 region获取4.4 secret_id和secret_key获取4.5 上传对象代码4.6 python实现上传文件 5 python创建桶 首先来到腾讯云官网 https://cloud.tencent.com/1. 开通服务 来…...
Springboot整合Jedis实现单机版或哨兵版可切换配置
Springboot整合Jedis实现单机版或哨兵版可切换配置 前言实现最后 前言 前文写到借助redis实现Shiro实现session限制登录数量踢人下线,本文就写一下Jedis的配置,可切换单机版和集群哨兵版,方便开发测试。 实现 很简单,直接上代码&…...

lenovo联想小新 Air-14 2019 AMD平台API版(81NJ)原装出厂Windows10系统
下载链接:https://pan.baidu.com/s/1HCC66EH4UOcgofRx5_v1oA?pwdlgqw 提取码:lgqw 原厂系统自带所有驱动、出厂主题壁纸、系统属性专属LOGO标志、Office办公软件、联想电脑管家等预装程序 所需要工具:16G或以上的U盘 文件格式…...

特殊矩阵的压缩存储(对称矩阵,三角矩阵,三对角矩阵,稀疏矩阵)
目录 1.数组的存储结构1.—维数组2.二维数组1.行优先存储2.列优先存储 2.特殊矩阵1.对称矩阵1.行优先存储 2.三角矩阵1.上三角矩阵2.下三角矩阵 3.三对角矩阵(带状矩阵)4.稀疏矩阵 1.数组的存储结构 1.—维数组 各数组元素大小相同,且物理上…...

DDU框架学习之路
目录 MVVM对比 DDU 数据消费者UI 数据的转换者:Domain Layer 数据图生产者/提供者 DataLayer 遵循原理: 单一数据流: Android官方推荐架构:DDU MVVM对比 M:Model 网络层 用于获取远端数据 VM:ViewModel 中间转…...
进阶课6——基于Seq2Seq的开放域生成型聊天机器人的设计和开发流程
情感聊天机器人通常属于开放领域,用户可以与机器人进行各种话题的互动。例如,微软小冰和早期的AnswerBus就是这种类型的聊天机器人。基于检索的开放领域聊天机器人需要大量的语料数据,其开发流程与基于任务型的聊天机器人相似,而基…...
Java面试题04
1.Array 和 ArrayList 有何区别? Array是固定长度的,元素类型可以是基本类型,创建后大小不可改变;ArrayList是可变长 度的,只能存储对象,可以动态添加和删除元素。 区别1: 存储类型不同 …...

海康Visionmaster-通讯管理:使用 Modbus TCP 通讯 协议与流程交互
使用 Modbus TCP 通讯协议与视觉通讯,当地址为 0000 的保持型寄存器(4x 寄存器)变为 1 时,触发视觉流程执行一次,同时视觉将地址为 0000 的寄存器复位(也即写为 0),视觉流程执行完成后,将结果数…...
assimp中如何判断矩阵是否是单位矩阵
对于一个矩阵元素为浮点型的矩阵,你是否还在使每个元素跟1.0f或0.0f进行比较,如果这样,只能说你的结果不一定正确,那我们看看assimp中是如何做的。 template <typename TReal> AI_FORCE_INLINE bool aiMatrix4x4t<TReal…...

大数据Doris(二十):数据导入(Broker Load)介绍
文章目录 数据导入(Broker Load)介绍 一、适用场景...
Docker快速安装kafka
创建zk docker run -d --name zookeeper-server \-e ALLOW_ANONYMOUS_LOGINyes \bitnami/zookeeper:latest创建kafka docker run -d --name kafka-server \-p 9092:9092 \-e ALLOW_PLAINTEXT_LISTENERyes \-e KAFKA_CFG_ZOOKEEPER_CONNECTzookeeper-server:2181 \-e KAFKA_CF…...

ChatGPT是什么?黑客试图淹没其服务
上线2个月,月活跃用户破亿,媒体人用它编辑文案,学生用它写作业,程序员用它编辑代码, 它是谁呢? 它就是火爆全网(chatgpt),chatgpt是什么呢,chatgpt是美国研发的一款人工…...

【Java 进阶篇】Java Web 开发之 Listener 篇:ServletContextListener 使用详解
欢迎大家来到 Java Web 开发的学习之旅!在前面的博客中,我们已经学习了 Servlet、JSP、Filter 等重要的概念和技术。今天,我们将深入探讨 Java Web 开发中另一个重要的组成部分——Listener(监听器),具体来…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...
用递归算法解锁「子集」问题 —— LeetCode 78题解析
文章目录 一、题目介绍二、递归思路详解:从决策树开始理解三、解法一:二叉决策树 DFS四、解法二:组合式回溯写法(推荐)五、解法对比 递归算法是编程中一种非常强大且常见的思想,它能够优雅地解决很多复杂的…...