从头开始学MyBatis—02基于xml和注解分别实现的增删改查
首先介绍此次使用的数据库结构,然后引出注意事项。
通过基于xml和基于注解的方式分别实现了增删改查,还有获取参数值、返回值的不同类型对比,帮助大家一次性掌握两种代码编写能力。
目录
数据库
数据库表
实体类
对应的实体类如下:
注意事项
1)两种占位符的说明
①#{}
②${}
2)增、删、改的返回值说明
3)查询操作
①必须指定resultType或是resultMap
4)对应关系
①数据库名与类名不一致的情况
②字段名与属性名不一致的情况
1.获取参数值的方式
1.1基于xml
1.1.1单个参数
①mapper
②xml
③test
④结果
1.1.2多个参数
①mapper
②xml
写法一
写法二
③test
④结果
1.1.3map参数
①mapper
②xml
③test
④结果
1.1.4实体类参数
①mapper
②xml
③test
④结果
1.1.5使用@Param标识参数
①mapper
写法一
写法二
错误写法
②xml
③test
④结果
1.2基于注解
1.2.1单个参数
①mapper
写法一
写法二
②test
③结果
1.2.2多个参数
①mapper
②test
③结果
1.2.3map参数
①mapper
②test
③结果
1.2.4实体类参数
①mapper
②test
③结果
1.2.5使用@Param标识参数
①mapper
写法一
写法二
②test
③结果
2.各种操作功能
2.1基于xml
2.1.1增
①mapper
②mapper.xml
③test
④结果
主键id自增并返回值
mapper
mapper.xml
test
结果
2.1.2删
①mapper
②mapper.xml
③test
④结果
删除前
删除后
2.1.3改
①mapper
②mapper.xml
③test
④结果
修改前
修改后
2.1.4查
①mapper
②mapper.xml
③test
④结果
2.2基于注解
2.2.1增
①mapper
②test
③结果
主键id自增并返回结果
mapper
test
结果
2.2.2删
①mapper
②test
③结果
删除前
删除后
2.2.3改
①mapper
②test
③结果
修改前
修改后
2.2.4查
①mapper
②test
③结果
3.各种返回值类型
3.1基于xml
①查询单条数据
②查询多条数据
3.2基于注解
①查询单条数据
②查询多条数据
数据库
数据库表
此次实验的数据库表结构如下,包含主键id和三个属性
实体类
对应的实体类如下:
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** ClassName: Book* Package: com.ykx.domain* Description: mybatis学习的数据库表tbl_book对应的实体类*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tbl_book")
public class Book {private Integer id;private String type;private String name;private String description;
}
注意事项
1)两种占位符的说明
①#{}
传入的参数当成一个字符串,会给传入的参数加单引号
能够很大程度上防止sql注入
一般用于替换某个值
②${}
将传入的参数值直接显示生成在sql中,不会自动加引号
预编译之前就已经被变量替换,无法防止sql注入
一般用于替换表、字段名
2)增、删、改的返回值说明
返回值固定位Integer,表示受影响的行数
3)查询操作
①必须指定resultType或是resultMap
不配置别名的时候,值为类的全类名
返回值是集合的时候,只需指定集合的泛型即可,如
List<Book> getAll();<select id="getAll" resultType="com.ykx.pojo.Book">select * from tbl_book
</select>
4)对应关系
①数据库名与类名不一致的情况
②字段名与属性名不一致的情况
1.获取参数值的方式
MyBatis 提供了多种传递参数的方式到 SQL 。
理解参数传递的机制有助于提高代码的可读性、灵活性。
1.1基于xml
1.1.1单个参数
①mapper
Book getById(Integer id);
②xml
在单个字面量参数的情况下,{}内的名称可以任意取
如下面的代码可以把#{id} 改成 #{ID}亦或是其他
<select id="getById" resultType="com.ykx.domain.Book">select * from tbl_book where id = #{id}
</select>
③test
@Test
public void testSelect(){Book book = bookMapperXML.getById(1);System.out.println(book);
}
④结果
1.1.2多个参数
①mapper
Book check(String type,String name);
②xml
写法一
<select id="check" resultType="com.ykx.domain.Book">select * from tbl_book where type = #{type} and name = #{name}
</select>
写法二
<select id="check" resultType="com.ykx.domain.Book">select * from tbl_book where type = #{param1} and name = #{param2}
</select>
③test
@Test
public void testCheck(){Book book = bookMapperXML.check("java","mybatis数据");System.out.println(book);
}
④结果
1.1.3map参数
①mapper
Book checkByMap(Map<String,String> map);
②xml
<select id="checkByMap" resultType="com.ykx.domain.Book">select * from tbl_book where type = #{type} and name = #{name}
</select>
③test
@Test
public void testCheckByMap(){Map<String,String> map = new HashMap<>();map.put("type","java");map.put("name", "mybatis数据");Book book = bookMapperXML.checkByMap(map);System.out.println(book);
}
④结果
1.1.4实体类参数
①mapper
Integer insert(Book book);
②xml
<insert id="insert">insert into tbl_book (type,name,description) values(#{type},#{name},#{description})
</insert>
③test
@Test
public void testInsert(){Book book = new Book(null,"计算机视觉","三维重建","基于深度学习的三维重建");Integer ans = bookMapperXML.insert(book);System.out.println("受影响的行数:" + ans);
}
④结果
1.1.5使用@Param标识参数
在字段名和属性名对不上或是参数名和字段名对不上的时候很有用
①mapper
写法一
Book check(@Param("type") String type, @Param("name") String name);
写法二
Book check(@Param("type") String type2, @Param("name") String name2);
错误写法
Book check(String type2, String name2);
②xml
<select id="check" resultType="com.ykx.domain.Book">select * from tbl_book where type = #{type} and name = #{name}
</select>
③test
@Test
public void testCheck(){Book book = bookMapperXML.check("java","mybatis数据");System.out.println(book);
}
④结果
1.2基于注解
1.2.1单个参数
①mapper
单个参数的情况下,接口的参数名和注解里的sql语句参数可以不一致
写法一
@Select("select * from tbl_book where id = #{id}")
Book getById(Integer id);
写法二
@Select("select * from tbl_book where id = #{aa}")
Book getById(Integer id);
②test
@Test
public void testSelect(){Book book = bookMapper.getById(78);System.out.println(book);
}
③结果
1.2.2多个参数
①mapper
注:在未使用@Param的情况下,参数名不对应或是顺序不一样会导致查询失败
@Select("select * from tbl_book where type = #{type} and name = #{name}")
Book getOne(String type,String name);
②test
@Test
public void testGetOne(){Book book = bookMapper.getOne("计算机视觉","三维重建");System.out.println(book);
}
③结果
1.2.3map参数
①mapper
@Select("select * from tbl_book where type = #{type} and name = #{name}")
Book getByMap(Map<String, String> map);
②test
注:map里的key值要和#{}里的值对应,否则出现查询失败的情况
@Test
public void testByMap(){Map<String,String> map = new HashMap<>();map.put("type","java");map.put("name", "mybatis数据");Book book = bookMapper.getByMap(map);System.out.println(book);
}
③结果
1.2.4实体类参数
①mapper
@Insert("insert into tbl_book (id,type,name,description) " +"values(#{id},#{type},#{name},#{description})")
Integer insert(Book book);
②test
@Test
public void testInsert(){Book book = new Book(null,"新增数据","测试新增","不带id的新增测试");Integer ans = bookMapper.insert(book);System.out.println("受影响的行数:" + ans);
}
③结果
1.2.5使用@Param标识参数
只需要#{}里的值和@Param()里的值一样就行
①mapper
写法一
@Select("select * from tbl_book where type = #{type} and name = #{name}")
Book getOne(@Param("type") String type,@Param("name") String name);
写法二
@Select("select * from tbl_book where type = #{type} and name = #{name}")
Book getOne(@Param("type") String typeaa,@Param("name") String nameaa);
②test
@Test
public void testGetOne(){Book book = bookMapper.getOne("计算机视觉","三维重建");System.out.println(book);
}
③结果
2.各种操作功能
2.1基于xml
2.1.1增
①mapper
//增:实体对象新增数据
Integer insert(Book book);
②mapper.xml
<insert id="insert">insert into tbl_book (id,type,name,description) values(#{id},#{type},#{name},#{description})
</insert>
注:这里设置了id主键自增的话,可以不设置和传入id
③test
//增:实体对象新增数据
@Test
public void testInsert(){Book book = new Book(71,"计算机视觉","三维重建","基于深度学习的三维重建");Integer ans = bookMapperXML.insert(book);System.out.println("受影响的行数:" + ans);
}
④结果
主键id自增并返回值
关键点:在xml里需要带上useGeneratedKeys和keyProperty
mapper
Integer autoId(Book book);
mapper.xml
<insert id="autoId" useGeneratedKeys="true" keyProperty="id">insert into tbl_book (type,name,description) values(#{type},#{name},#{description})
</insert>
test
//增:主键自增且返回值
@Test
public void testAutoId(){Book book = new Book(null,"测试id自增","返回主键id","是否成功获取id的值");Integer ans = bookMapperXML.autoId(book);System.out.println("受影响的行数:" + ans);System.out.println("获取主键自增的id值:" + book.getId());
}
结果
2.1.2删
①mapper
//删:根据id删除数据
Integer delete(Integer id);
②mapper.xml
<delete id="delete">delete from tbl_book where id = #{id};
</delete>
③test
//删:根据id删除数据
@Test
public void testDelete(){Integer ans = bookMapperXML.delete(68);System.out.println("受影响的行数:" + ans);
}
④结果
删除前
删除后
2.1.3改
①mapper
//改:根据id修改数据
Integer update(Book book);
②mapper.xml
<update id="update">update tbl_book set type = #{type},name = #{name},description = #{description} where id = #{id};
</update>
③test
//改:根据id修改数据
@Test
public void testUpdate(){Book book = new Book(58,"测试修改","mybatis修改","基于xml的修改操作");Integer ans = bookMapperXML.update(book);System.out.println("受影响的行数:" + ans);
}
④结果
修改前
修改后
2.1.4查
①mapper
@Mapper
public interface BookMapperXML {//查:根据id查询数据Book getById(Integer id);//查:查询所有数据List<Book> getAll();}
②mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ykx.mapper.BookMapperXML"><select id="getById" resultType="com.ykx.domain.Book">select * from tbl_book where id = #{id}</select><select id="getAll" resultType="com.ykx.domain.Book">select * from tbl_book</select>
</mapper>
③test
@SpringBootTest
public class XMLMybatisTest {@Autowiredprivate BookMapperXML bookMapperXML;//查:根据id查询数据@Testpublic void testSelect(){Book book = bookMapperXML.getById(1);}//查:查询所有数据@Testpublic void testGetAll(){List<Book> books = bookMapperXML.getAll();for(Book book : books){System.out.println(book);}}}
④结果
2.2基于注解
2.2.1增
①mapper
@Insert("insert into tbl_book (id,type,name,description) " +"values(#{id},#{type},#{name},#{description})")
Integer insert(Book book);
②test
//增:实体对象新增数据
@Test
public void testInsert(){Book book = new Book(11,"新增数据","测试新增","带id的新增测试");Integer ans = bookMapper.insert(book);System.out.println("受影响的行数:" + ans);
}
③结果
主键id自增并返回结果
关键点:在mapper对应的方法上面加上@Options注解,并设置useGeneratedKeys和keyProperty的属性值。这个只能搭配insert语句使用!
mapper
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into tbl_book (type,name,description) " +"values(#{type},#{name},#{description})")
Integer autoId(Book book);
test
//增:主键自增且返回值
@Test
public void testAutoId(){Book book = new Book(null,"新增数据2","测试新增2","不带id的新增测试");Integer ans = bookMapper.autoId(book);System.out.println("受影响的行数:" + ans);System.out.println("获取主键自增的id值:" + book.getId());
}
结果
2.2.2删
①mapper
//删:根据id删除数据
@Delete("delete from tbl_book where id = #{id}")
Integer delete(Integer id);
②test
//删:根据id删除数据
@Test
public void testDelete(){Integer ans = bookMapper.delete(8);System.out.println("受影响的行数:" + ans);
}
③结果
删除前
删除后
2.2.3改
①mapper
//改:根据id修改数据
@Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}")
Integer update(Book book);
②test
//改:根据id修改数据
@Test
public void testUpdate(){Book book = new Book(62,"测试修改","mybatis修改","基于注解的修改操作");Integer ans = bookMapper.update(book);System.out.println("受影响的行数:" + ans);
}
③结果
修改前
修改后
2.2.4查
①mapper
//查:根据id查询数据
@Select("select * from tbl_book where id = #{id}")
Book getById(Integer id);//查:查询所有数据
@Select("select * from tbl_book")
List<Book> getAll();
②test
//查:根据id查询数据
@Test
public void testSelect(){Book book = bookMapper.getById(71);System.out.println(book);
}//查:查询所有数据
@Test
public void testGetAll(){List<Book> books = bookMapper.getAll();for(Book book : books){System.out.println(book);}
}
③结果
3.各种返回值类型
对于增、删、改操作一般返回值类型为integer,表示数据表受影响的行数。对于查询操作,一般返回值类型为实体类或是集合类型。
前面已经对增、删、改返回integer进行了测试,这里就不再赘述,下面对查询操作的返回值进行一个总结。
3.1基于xml
①查询单条数据
mapper层接口用对应的实体类接收
//查:根据id查询数据
Book getById(Integer id);
xml文件设置resultType为具体的实体类类型
<select id="getById" resultType="com.ykx.domain.Book">select * from tbl_book where id = #{id}
</select>
②查询多条数据
mapper层接口用List集合接收,其泛型为对应的实体类类型
//查:查询所有数据
List<Book> getAll();
xml文件设置resultType为具体的实体类类型
<select id="getAll" resultType="com.ykx.domain.Book">select * from tbl_book
</select>
3.2基于注解
①查询单条数据
mapper层接口的返回值类型设置为对应的实体类类型即可
//查:根据id查询数据
@Select("select * from tbl_book where id = #{id}")
Book getById(Integer id);
②查询多条数据
mapper层接口的返回值类型设置为List集合,其泛型为对应的实体类类型即可
//查:查询所有数据
@Select("select * from tbl_book")
List<Book> getAll();
原创内容 未经同意禁止转载 如有引用请标明出处
相关文章:

从头开始学MyBatis—02基于xml和注解分别实现的增删改查
首先介绍此次使用的数据库结构,然后引出注意事项。 通过基于xml和基于注解的方式分别实现了增删改查,还有获取参数值、返回值的不同类型对比,帮助大家一次性掌握两种代码编写能力。 目录 数据库 数据库表 实体类 对应的实体类如下&#x…...

AI音乐创作的新时代:从创意到旋律的智能化转型
文章目录 🎼 AI音乐创作的新时代:从创意到旋律的智能化转型1 AI在音乐创作中的应用1.1 AI如何生成音乐? 2 常见的AI音乐创作工具2.1 AIVA2.2 Ecrett Music2.3 Jukedeck 3 AI音乐创作的流程3.1 第一步:确定音乐风格和情感基调3.2 第…...

Spring Boot集成Akka remoting快速入门Demo
1.什么是Akka remoting? Akka-Remoting一种ActorSystem之间Actor对Actor点对点的沟通协议.通过Akka-Remoting来实现一个ActorSystem中的一个Actor与另一个ActorSystem中的另一个Actor之间的沟通 Akka Remoting限制: 不支持NAT(Network Add…...

JVM 调优篇7 调优案例1-堆空间的优化解决
一 jvm优化 1.1 优化实施步骤* 1)减少使用全局变量和大对象; 2)调整新生代的大小到最合适; 3)设置老年代的大小为最合适; 4)选择合适的GC收集器; 1.2 关于GC优化原则 多数的Java应用不需要在服务器上进行GC优化࿱…...

文件格式转换:EXCEL和CSV文件格式互相转换
目录 1.EXCEl和CSV文件格式互相转换1.1首先安装所需的Python包1.2excel转换为csv代码如下:1.3csv转换为excel代码如下:由于excel文件在数学建模数据处理当中的局限性,我们通常把excel文件转换为csv文件来处理,下面是相关的代码,我直接封装成函数,你们直接调用即可,我会添…...

基于协同过滤的北京森林公园推荐---附源码74454
摘要 本论文主要论述了如何基于协同过滤开发一个北京森林公园推荐,本系统将严格按照软件开发流程进行各个阶段的工作,通过爬虫技术对北京森林公园的景点信息数据进行爬取,面向对象编程思想进行项目开发。在引言中,作者将论述北京森…...

002 JavaClent操作RabbitMQ
Java Client操作RabbitMQ 文章目录 Java Client操作RabbitMQ1.pom依赖2.连接工具类3.简单模式4.工作队列模式(work)公平调度示例 5.发布/订阅模式(fanout)交换机绑定示例代码 6.路由模式(direct)7.Topic匹配…...

lablelme标注的数据转成YOLO v8 格式
1 labelme 转 yolov8 格式 import json import cv2 import numpy as np import os def json2yolo(path):# dic{N_shaoxi:0, N_qiaoqi:1, N_qiaojie:2, N_pianyi:3, N_yiwu: 4, \# NV_shaoxi: 5, NV_qiaoqi: 6, NV_qiaojie: 7, NV_pianyi: 8, NV_yiwu: 9,\# …...

【linux】cat 命令
cat 命令是 Linux 和 Unix 系统中非常基础且常用的一个命令,它的全称是 "concatenate" 的缩写,意为“连接”或“串联”。尽管名字听起来像是专门用于连接文件的,但 cat 命令的用途远不止于此。它主要用于查看、创建、合并文件内容&…...

速通sass基础语法
速通Sass语法: sass的特点: 由于css的缺陷:无法自定义变量,不可引用,嵌套等。sass/scss/less等css预处理器产生。以sass为例,引入了变量、嵌套、运算、混入(Mixin)、继承、颜色处理、函数等诸多功能。方便…...

Vue: watch5种监听情况
目录 一.watch的性质与作用 1.watch 的性质包括: 2.watch 常用于以下场景: 二.监视ref定义的基本类型数据 三.监视ref定义的对象类型数据 四.监视reactive定义的对象类型数据 五.监视ref或reactive定义的对象类型数据中的某个属性 六.监视上述的…...

Android 车联网——汽车系统介绍(附2)
汽车系统指的是由多个模块或组件组成的系统,如发动机系统、制动系统、空调系统等,这些系统通常由多个 ECU 协同工作来完成特定的任务。 一、汽车系统 1、防抱死制动系统 ABS(Anti-lock Braking System,防抱死制动系统)是一项重要的汽车安全技术,其主要功能是在车辆紧急…...

C++ 链表
基本用法 C++提供了list容器,这是一个双向链表,能高效进行数据添加和删除。 引入头文件 #include <iostream> #include <list> // 引入list头文件 using namespace std;创建和初始化 list...

中国初创公司数量下降了98%
近年来,中国风险投资市场的风云变幻,通过IT Juzi(IT桔子)等权威数据服务提供商的透镜,得以清晰展现。数据显示,自2018年的鼎盛时期——拥有51,302家初创公司以来,这一数字在短短五年内急剧下降至…...

【SSRF漏洞】——http协议常见绕过
改变的确很难,但结果值得冒险 本文如有错误之处,还请各位师傅指正 一.ssrf概述 SSRF全称为Server-side Request Fogery,中文含义服务器端请求伪造 SSRF是一种由攻击者构造形成由目标服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标…...

[网络][CISCO]CISCO_华为网络设备端口镜像配置
CISCO 华为网络设备端口镜像配置大全 isco交换机通常支持2组镜像,4000系列有支持6组镜象的。支持所全端口镜像。 Cisco catylist2820 有2个菜单选项 先进入menu选项,enable port monitor 进入cli模式, en conf term interface fast0/…...

第二十五章 添加数字签名
文章目录 第二十五章 添加数字签名数字签名概述添加数字签名 第二十五章 添加数字签名 本主题介绍如何向 IRIS Web 服务和 Web 客户端发送的 SOAP 消息添加数字签名。 通常,会同时执行加密和签名。为简单起见,本主题仅介绍签名。有关结合加密和签名的信…...

GHOST重装后DEF盘数据救援指南
一、现象解析:GHOST重装后的DEF盘失踪之谜 在计算机维护的日常中,GHOST重装因其快速便捷的特点,成为众多用户解决系统问题的首选方法。然而,这一操作虽能迅速恢复系统至初始状态,却也暗藏风险,尤其是当不慎…...

使用blender快速制作metahuman面部以及身体绑定教程
【metablriger教程】使用blender一键绑定自定义角色metahuman绑定并导入UE5引擎教程_哔哩哔哩_bilibili 目前市面上的制作metahuman绑定的工具大多是maya的,metablriger是一个帮助用户快速制作metahuman绑定的blender插件,可以平替市面上已有的metahuma…...

OpenHarmony鸿蒙( Beta5.0)智能窗户通风设备开发详解
鸿蒙开发往期必看: 一分钟了解”纯血版!鸿蒙HarmonyOS Next应用开发! “非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线!(从零基础入门到精通) “一杯冰美式的时间” 了解鸿蒙HarmonyOS Next应用开发路…...

pandas 将多条记录整合成一条记录,每条记录的year和month字段组成新的字段名
你可以使用 Pandas 的 pivot_table() 或 groupby() 方法,将多条记录整合成一条,并通过 year 和 month 这两个字段生成新的字段名。具体的实现方法是通过 pivot_table() 将 year 和 month 作为列标签,将其他列中的数据进行整合。 假设你的数据…...

C# 中的多线程同步:原子变量、原子操作、内存顺序和可见性
C# 中的多线程同步:原子变量、原子操作、内存顺序和可见性 引言 随着现代计算机系统的发展,多核处理器已经变得非常普遍。在这种环境下,多线程编程成为提高应用程序性能的关键技术之一。然而,多线程编程带来了新的挑战ÿ…...

视图(mysql)
一、什么是视图 视图是⼀个虚拟的表,它是基于⼀个或多个基本表或其他视图的查询结果集。视图本⾝不存储数 据,⽽是通过执⾏查询来动态⽣成数据。⽤⼾可以像操作普通表⼀样使⽤视图进⾏查询、更新和管 理。视图本⾝并不占⽤物理存储空间,它仅…...

elementui组件el-upload实现批量文件上传
el-upload组件上传文件时,每传一个文件会调一次接口,所以当上传多个文件的时候,有 n 个文件就要调 n 次接口。 刚好之前工作中遇到使用el-upload组件批量上传文件的需求,来看看怎么实现。 思路: 1.取消组件的自动上…...

【JAVA入门】Day45 - 压缩流 / 解压缩流
【JAVA入门】Day45 - 压缩流 / 解压缩流 文章目录 【JAVA入门】Day45 - 压缩流 / 解压缩流一、解压缩流二、压缩流 在文件传输过程中,文件体积比较大,传输较慢,因此我们发明了一种方法,把文件里的数据压缩到一种压缩文件中&#x…...

Qt_自定义信号
目录 1、自定义信号的规定 2、创建自定义信号 3、带参数的信号与槽 4、一个信号连接多个槽 5、信号与槽的断开 结语 前言: 虽然Qt已经内置了大量的信号,并且这些信号能够满足大部分的开发场景,但是Qt仍然允许开发者自定义信号&#…...

【运维方案】某系统运维需求方案参考(doc全原件2024)
系统运维需求方案 1服务目标 2服务人力需求、服务资源需求 3信息资产统计服务需求 4业务应用软件服务需求 5网络、安全系统运维服务需求 6主机、存储系统运维服务需求 7数据库系统运维服务需求 8终端运维服务需求 9综合布线系统服务需求 10大屏幕显示系统的维护需求 11视频会议…...

Linux环境使用Git同步教程
📖 前言:由于CentOS 7已于2024年06月30日停止维护,为了避免操作系统停止维护带来的影响,我们将把系统更换为Ubuntu并迁移数据,在此之前简要的学习Git的上传下载操作。 目录 🕒 1. 连接🕘 1.1 配…...

c++临时对象导致的生命周期问题
对象的生命周期是c中非常重要的概念,它直接决定了你的程序是否正确以及是否存在安全问题。 今天要说的临时变量导致的生命周期问题是非常常见的,很多时候没有一定经验甚至没法识别出来。光是我自己写、review、回答别人的问题就犯了或者看到了许许多多这…...

CSP-J 算法基础 深度优先搜索
文章目录 前言深度优先搜索通俗解释例子深度优先搜索的步骤DFS 的特点生活中的类比 为什么递归问题会变成深度优先搜索?递归与深度优先搜索的关系:递归与系统栈递归调用的过程:栈的作用: 递归与系统栈的简单示例递归实现 DFS 的简…...