【JavaEE】懒人的福音-MyBatis框架—复杂的操作-动态SQL
【JavaEE】MyBatis框架要点总结(3)
文章目录
- 【JavaEE】MyBatis框架要点总结(3)
- 1. 多表查询
- 1.1 映射表resultMap
- 1.2 只有部分属性跨表查询
- 1.2.1 依照常规去写代码
- 1.2.2 用标签去实现接口
- 1.3 分多步的解决方案
- 1.4 与多线程的结合
- 2. 动态SQL
- 2.1 if 标签
- 2.2 test值
- 2.3 trim标签
- 2.4 where标签
- 2.5 set标签
- 2.6 foreach标签
- 2.6.1 通过Integer数组批量删除
- 2.6.2 通过UserInfo集合批量插入
- 2.6.3 传入多个集合
- 3. 最后的碎碎念 of MyBatis完结✿✿ヽ(°▽°)ノ✿
【JavaEE】MyBatis框架要点总结(3)
上一篇文章,我们学习了MyBatis框架对数据库的各种单表操作,想必已经对增删改查语法已经熟悉很多了
但是,我们学习的只是一些固定的功能,更复杂的业务要求还是不能满足:
- insert一个对象,如果这个对象有些属性是没有被赋值的,则插入的时候,values中不传值
- 因为对象属性的默认值,并不一定是数据库表的字段的默认值
- 批量增删…
- 多表查询…
- 等等…
我们先从多表查询讲起~
1. 多表查询
有些时候,我们要的信息并非在同一张表中(其实很少,因为一般一个实体类就代表一张表)
- 这个时候就需要联合查询了~
1.1 映射表resultMap
这种方法很麻烦,无非就是能手动加一些映射关系而实现功能,个人觉得比较暴力:
大概代码差不多长这样:
<resultMap id="BaseMap” type="com.example.demo .model.ArticleInfo".<id property="id” column="id"></id><result property="title" column="title"></result><result property="content" column="content"></result><result property="createtime" column="createtime"></result><result property="updatetime" column="updatetime"></result><result property="uid" column="uid"></result><result property="rcount" column="rcount"></result><result property="state"” column="state"></result><association property="user" resultMap="com.example.demo.mapper.UserMapper.BaseMap" columnPrefix="u_"></association> </resultMap> <select id="getAll" resultMap="BaseMap">select a.*,u.username u username from articleinfo aleft join userinfo u on a.uid=u.id </select>
association标签,可实现一篇文章对应一个作者
除此之外,还有collection标签去实现一个用户对应多篇文章
太麻烦了,可读性不高,基本不会有人会用的,所以我不演示了~
1.2 只有部分属性跨表查询
对于这种情况的话,就不需要,查询出另一张表的整个实体对象了~
例如一篇博客文章联合上作者的名字:
当然,如果你要携带一个对象也不是不行,把他的属性全部写一遍~
- 特别不建议,这样很不美观
- 并且只能一对一,不能一对多
其实一遍情况下,这样是够用的,因为我们在实际场合中,一对一都只需要另一张表的几个重要信息!
这种情况,则跟平常的写法一致:
- 因为 “赋值规则” 是以 最终呈现的表的情况为准
- 即, 只要通过联合查询方式出现的列,都能赋值给属性
创建对应的mapper接口和xml文件:
- 低耦合高内聚,封装和隔离嘛
1.2.1 依照常规去写代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.ArticleMapper"></mapper>
测试:
效果:
原理就是:
- 最终呈现的表的列是可以赋值的
1.2.2 用标签去实现接口
注解代替xml的原理:
- @Select代替select标签
- 增删改查对应增删改查的注解
- 加在哪个方法上id就是啥,resultType就是其返回类型
- 注解内的字符串,就是原标签内部的sql代码
测试:
结果一致:
在这样的简单内部sql代码而言,这样写很方便,而在复杂的操作下,并不是很方便~
- 例如,等一下要讲的动态sql代码
- 弊端:引号限制,书写字符串禁锢思想…
1.3 分多步的解决方案
对于一对多(例如一个作者携带多篇文章)情况,我们一般采取, 分多步的解决方案(数据库没有集合类型)
假设要找的用户为id=1
- 在userinfo中去找id等于1的用户对象
- 在articleinfo中去找uid等于1的文章对象
- 合并结果
实现:
效果:
1.4 与多线程的结合
有时候面试官可能会问你,你的项目有没有结合多线程呢?
你可能不知道怎么回答,但是你可以说,多表查询的时候,可以用到线程池!
- 两张表同时查后一起合并~
- 没有线程安全问题,提高CPU利用率,提高代码效率
代码实现:
- 线程池博客:【JavaEE】线程案例-定时器-线程池 and 工厂模式_s:103的博客-CSDN博客
- 等待线程结束方法博客:【JavaEE】Callable接口(NO.6线程创建方法)-JUC的常见类-与线程安全有关集合类_s:103的博客-CSDN博客
获得线程池:
用计数员CountDownLatch去判断线程是否结束:
等待两个线程结束才继续后面的内容:
效果:
多表查询讲完后,就是MyBatis篇章的最后一个内容:动态SQL
2. 动态SQL
主要是因为,这是xml去实现接口的方法,并不像jdbc编程,我们可以用java做一些自定义的业务逻辑去构造sql字符串,到目前为止的功能,似乎都是我们写死的,但是如果要用jdbc结合java代码去写一些操作,也是麻烦的
例如:
我们并不能给枚举每个种情况,写那么多的方法!
然后通过笨方法去判断使用哪个方法!
因此MyBatis在xml是实现接口中加入了语法:动态SQL
- 在标签中编写sql代码的杂合语法
- 标签进行一些业务逻辑,再呈现出最终的SQL语句
千万别把这个过程看成写字符串,而是书写代码
即让方法实现有了逻辑的,是活的,是动态的SQL;又让方法实现更加简单,这就是框架的意义!
接下来讲解实现常见逻辑的便签:(等一下记得题一下,注解这样写不方便!还有引号不方便,开发不方便,写字符串的限制…)
2.1 if 标签
对于这个要求,其实在很多场合都会出现,例如填报信息中的*必选项
和非必选项
- 这样导致最终提交的信息,属性的赋值情况参差不齐,啥情况都有
而if标签实现的逻辑,就可以很好的解决这个问题
补充:
- state的值是0或者是1,而对象中没有被赋值是0,无法判断这个值是否是有效值
- 所以state在定义时应该改为Integer类型
- 可以看出,基本数据类型的包装类,只有在不得不写的时候才会用~
xml实现:
显然这段代码不能复制给之前注解实现的方法的括号里,因为写法不方便,并且有引号的限制
测试:
效果:
数据库:
数据库:
想必你能感受到一点,“动态”的感觉,动态SQL就是MyBatis的一个强大特性
2.2 test值
test值的内容就是,一段java代码的逻辑表达式,结果true或者是false
test值中的对象的变量名:
- 传入自定义对象的属性名(由于传入自定义对象,就必然是单参,所以就只是这个对象中的属性)
- 传入多个参数的参数名(默认/自己设置)
不需要#{}
去包起来,就看成java代码,直接使用变量名代表变量!
- 不规范写法就等着报错吧 (╬▔皿▔)凸
传入多个参数:
效果:
数据库:
2.3 trim标签
其实,刚才的要求并没有,完成,还是有可能会出bug
- 报错可以,但是报的错应该是必选项没有填,而不是sql语句错误
正确的报500:
- 这个错是因为数据库的userinfo表,规定了username和password是不能为空的,也就是说, 必须传这两个值,否则就会这样报错,以此实现“必选项”的功能
错误的报500:
原因是:SQL语句变成了:
insert into userinfo(username, password,) values(#{username}, #{password},)
那两个逗号,导致sql语句不符合语法!
而trim标签的出现,就是为了避免这样以及类似的语法错误!
- trim标签的 “修理功能”,可以有效解决,这些前缀后缀,分隔符的问题
trim标签的功能分为四个属性:
- prefix
- 如果语块内进行一系列标签的逻辑操作动态变化后,最终不为空,增加前缀prefix
- suffix
- 如果语块内进行一系列标签的逻辑操作动态变化后,最终不为空,增加后缀suffix
- prefixOverrides
- 如果语块内进行一系列标签的逻辑操作动态变化后,前缀为prefixOverrides,则删除
- suffixOverrides
- 如果语块内进行一系列标签的逻辑操作动态变化后,后缀为prefixOverrides,则删除
优化刚才的代码:
方法的实现:
测试:
效果:
- 多余的后缀去掉了,并且括号加上了
数据库:
补充:可想而知,如果啥也不传,就是:
insert into userinfo values;
显然是语法错误的,但是也正常,因为啥也不传本来就不合理,啥也没有干哈子添加操作~
- 即使一张表每个字段都有默认值,但是一个都不传,本身就是不合实际的!
- 这个点不需要解决,就该报500
在sql语句后加一些空格、换行、tab等空白符,不会影响后缀的判断
- 不演示…
2.4 where标签
其实trim的功能更加灵活,可以实现的功能很全面了,静待你的发挥
而where标签,则是trim中的一种特殊而且常见的情况,用于条件查询的where条件:
select * from userinfo where username = #{username} and password = #{password} and state = #{state};
- 这个方法的功能是,查询所有跟传过来的userinfo已有属性值都相同的用户
- 如果userinfo中属性都没被赋值,则就是全表查询
- 被赋值的越少,条件越简单
xml实现:
但是,你也会很快意识到,这会出现 where and
的情况出现!
测试:
效果:
错误效果:
where没去掉
出现了
where and
所以就有了where标签:
- 如果语块最终非空,则默认在前面加where前缀
- 如果语块最终的前缀and或者or会去除
- 没有涉及NOT
- 只适合简单的删除前缀and/or,不涉及其他复杂的逻辑表达式
- 其实sql本身逻辑表达式在实际情况里不会很复杂,最多就这样了!
- 标签的功能是有限的,我们要遵守框架规则,才能吃到框架的红利!
- 在前面就不要加where了,否则就会出现两个where的情况!
效果:
where本质其实就是这样:
<trim prefix="where" prefixOverrides="and"><trim prefixOverrides="or"></trim>
</trim>
测试:
注意:
- 删除and/or,只是前缀
- 后缀不行!
效果:
2.5 set标签
跟where标签一样,也是trim标签的一种特殊的创建情况,主要是代替修改操作的set语句:
update username set state = 0, username = '尊嘟假嘟' where id = #{id};
同样的,里面的逗号,
,可能会出现set ,
的尴尬情况
所以set标签能解决这个问题:
- 语句非空,加前缀set
- 抹除后缀的逗号
,
相当于这个trim标签:
<trim prefix="set" suffixOverrides=","></trim>
接口方法:
- 要求:根据这个用户信息的id,将username password state属性更新到表里对应的用户
xml实现:
测试:
效果:
- 用户名赋值的是
'尊嘟假嘟'
; 密码赋值的是'666'
哦
数据库:
注意:前缀逗号不会被去掉的,并且前面别加set,否则会出现
set set
的情况,其他应用猜猜就能写了,交给你了…
2.6 foreach标签
顾名思义就是,遍历集合/数组的意思,这个标签常常用于批量增删的操作
- 并且没有这个标签,是不能传入
List<Object>
或者Object[]
,因为数据读不了~ - 批量操作的出现概率也比较低,之前我们对于批量操作,是用for循环进行n次的数据库操作,而不是一次到位
foreach有以下属性:
- collection:绑定方法参数中的集合名
- 可以是List,Map,Set,数组…
- item:遍历时的每一个对象
- open和close:语句非空时的前后缀
- separator:每次遍历的数据之间的分隔符
- index,循环变量,从0开始一次循环加一,不常用~
java代码的理解(伪代码):
String subSQL = "delete from userinfo where id in ";
subSQL += "(";
for(Object item : collection) {subSQL += #{item.property};//自动检测要不要添加分隔符separator
}
subSQL += ")";
2.6.1 通过Integer数组批量删除
xml实现:
- 就是打算将Integer集合转化为(1,2,3)的这种形式跟in搭配!
测试:
效果:
数据库:
2.6.2 通过UserInfo集合批量插入
xml实现:
- 我写的测试用例信息全面,重点突出foreach标签的功能,虽然可以和其他标签结合使用发挥更大的功能,所以我的写法并不全面,通用性不高~
- 这里讲基础,更多想法和应用交给你咯😀😀😀
- 但是在这里还是以讲解foreach功能为主!
测试:
准备测试用例:
注意添加不带参数的构造方法,不然Bean对象无法存储
- 因为我们自己写的构造方法会顶替原来的构造方法
效果:
数据库:
2.6.3 传入多个集合
我猜测,主要是因为传入的集合的,有可能是Integer,String…的非自定义对象集合,我们有时候需要传入多个这样的不同类型的集合,原本的@Param显然不适用了~
- 所以foreach标签提供的机制是 collection去连接集合,item规定对象名
- 非自定义类型集合中的一个的包装类元素,起了个名item,可以
#{item}
- (直接)跟元素(已是最小单元)建立对应
- 自定义类型集合中的一个对象元素,起了个名item,可以
#{item.property}
- (间接)跟元素的属性建立对应
- 因此,我们反而可以传入两个自定义类型集合等多个集合,因为不会出现冲突
效果:
数据库:
3. 最后的碎碎念 of MyBatis完结✿✿ヽ(°▽°)ノ✿
在MyBatis的学习过后,想必你有很多想法,因为我讲的毕竟是常见写法,至于他们杂合起来是什么样的,这就是你可以发挥的了!
如果可以,可以去学习MyBatis Plus的语法!
实际后端需要的sql有关的逻辑,不会再复杂了,即使有,也应该在使用接口方法前进行简化,趋向于按照框架的规定进行操作,所以不要焦虑于用这些标签进行复杂逻辑操作!
其实后端程序操作数据库,都应该是简单且安全的sql语句,所以创建库创建表,删库删表等操作都不是程序来操作的,虽然jdbc能够实现这些操作,但是学了没用!
我们学会的就是技能,用这些技能,有了思想,要怎么实现功能,能实现什么功能,发挥你的头脑,去自由的应用吧,都能实现的了的!
你可能发现你的知识按照这个逻辑来实现某个功能是可行的,对,就这么去猜,然后去实践它!
我做不到把每个属性每个语法都讲,但是这些足以实现会遇到的问题了!
- 即使会遇到不会的,就上网去学,因为更多巧妙的东西还可以进一步去学!
- 主打个“有需要再学”
文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆!代码位置:mybatis_demo/src · 游离态/马拉圈2023年8月 - 码云 - 开源中国 (gitee.com)
相关文章:

【JavaEE】懒人的福音-MyBatis框架—复杂的操作-动态SQL
【JavaEE】MyBatis框架要点总结(3) 文章目录 【JavaEE】MyBatis框架要点总结(3)1. 多表查询1.1 映射表resultMap1.2 只有部分属性跨表查询1.2.1 依照常规去写代码1.2.2 用标签去实现接口 1.3 分多步的解决方案1.4 与多线程的结合 …...
Springboot 默认路径说明
Spring Boot基本上是Spring框架的扩展,它消除了设置Spring应用程序所需的样板配置,极大的方便了开发者,其默认识别路径如下: Spring Boot 作为Spring默认将 /** 所有访问映射到以下目录: 1、classpath:/static 用于加…...
springboot注册拦截器与返回统一标准响应格式
响应对象ResultVO package com.example.poi.utils;import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.io.Serializable;/*** A…...

卷王特斯拉又全网降价了,卷死车企们
哈喽,大家好,今天媒介盒子小编又来跟大家分享软文推广的干货知识了,本篇分享的主要内容是:特斯无孔不入的营销手段。 1、特斯拉Model Y降价 车企要打架 自2023 年 8 月 14 日起,Model Y 长续航版起售价从 31.39 万元调整为 29.99 万元,Mode…...

wiley:revision 流程
1 上传修改后的word文件 注意:包括没标注修改位置的word文件和标注了修改位置的word文件 2 上传response回复文件 Your Author Response should include relevant comments that you have copied from the decision letter, along with your comments detailing …...

【论文阅读】基于深度学习的时序预测——Pyraformer
系列文章链接 论文一:2020 Informer:长时序数据预测 论文二:2021 Autoformer:长序列数据预测 论文三:2022 FEDformer:长序列数据预测 论文四:2022 Non-Stationary Transformers:非平…...

玩转IndexedDB,比localStorage、cookie还要强大的网页端本地缓存
随着浏览器的功能不断增强,越来越多的网站开始考虑,将大量数据储存在客户端,这样可以减少从服务器获取数据,直接从本地获取数据。 现有的浏览器数据储存方案,都不适合储存大量数据:Cookie 的大小不超过 4K…...

RedisDesktopManager连不上redis问题解决(小白版)
常见问题就是 redis.conf配置文件 a.将port 127.0.0.1这一行注释掉 b.protected-mode保护模式改为no 这个可以看到很多博主都说了,相信都搜到这里来了你们都弄了,我就不详细说了 防火墙开放端口 我说明我自己的问题以及解决方法 1、执行telnet 虚拟…...

蓝帽杯 取证2022
网站取证 网站取证_1 下载附件 并解压 得到了一个文件以及一个压缩包 解压压缩包 用火绒查病毒 发现后门 打开文件路径之后 发现了一句话木马 解出flag 网站取证_2 让找数据库链接的明文密码 打开www文件找找 查看数据库配置文件/application/database.php(CodeI…...
MyBatis and or使用列表控制or条件
背景:最近项目需要,师傅可以查找订单,而师傅是指定可以服务2到3个区域,故需要使用到and, or条件的组合,以下记一下代码。 最重要的代码是: 1、构建List<Consumer<LambdaQueryWrapper<T>>&g…...

C语言刷题训练【第11天】
大家好,我是纪宁。 今天是C语言笔试刷题训练的第11天,加油! 文章目录 1、声明以下变量,则表达式: ch/i (f*d – i) 的结果类型为( )2、关于代码的说法正确的是( )3、已知有如下各变…...

正则表达式的使用
1、正则表达式-教程 正则表达式:文本模式,包括普通字符(例如,a到z之间的字母)和特殊字符(称为元字符)。 正则表达式使用单个字符串来描述,匹配一系列匹配某个句法规则的字符串。 2、…...

PHP 求解两字符串所有公共子序列及最长公共子序列 支持多字节字符串
/*** 获取两字符串所有公共子序列【不连续的】 例:abc ac > ac** param string $str1 字符串1* param string $str2 字符串2** return array*/ function public_sequence(string $str1, string $str2): array {$data [[-1, -1, , 0, ]]; // 子序列容器【横坐标 …...
linux内核bitmap之setbit汇编实现
内核版本:kernel 0.12 首先看一段代码,下面这段代码来自内核版本0.12的mm/swap.c中: // mm/swap.c #define bitop(name,op) \static inline int name(char * addr,unsigned int nr) \ { \int __res; \__asm__ __volatile__("bt" …...
Golang设计模式
Golang设计模式 Golang设计模式简介Golang工厂设计模式Golang单例设计模式Golang抽象工厂设计模式Golang建造者模式 (Builder Pattern)Golang 原型模式(Prototype Pattern)Golang适配器模式Golang 桥接模式(Bridge Pattern)Golang装饰器模式(Decorator …...
leetcode151. 反转字符串中的单词
题目:leetcode151. 反转字符串中的单词 描述: 给你一个字符串 s ,请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。 返回 单词 顺序颠倒且 单词 之间用单个空格连接的结…...

【BASH】回顾与知识点梳理(十七)
【BASH】回顾与知识点梳理 十七 十七. 什么是 Shell scripts17.1 干嘛学习 shell scripts自动化管理的重要依据追踪与管理系统的重要工作简单入侵检测功能连续指令单一化简易的数据处理跨平台支持与学习历程较短 17.2 第一支 script 的撰写与执行撰写第一支 script 17.3 撰写 s…...

时序预测-Informer简介
文章目录 Informer介绍1. Transformer存在的问题2. Informer研究背景3. Informer 整体架构3.1 ProbSparse Self-attention3.2 Self-attention Distilling3.3 Generative Style Decoder 4. Informer的实验性能5. 相关资料 Informer介绍 1. Transformer存在的问题 Informer实质…...
2023牛客第七场补题报告C F L M
2023牛客第七场补题报告C F L M C-Beautiful Sequence_2023牛客暑期多校训练营7 (nowcoder.com) 思路 观察到数组一定是递增的,所以从最高位往下考虑每位的1最多只有一个,然后按位枚举贪心即可。 代码 #include <bits/stdc.h> using namespac…...

Android使用kotlin+协程+room数据库的简单应用
前言:一般主线程(UI线程)中是不能执行创建数据这些操作的,因为等待时间长。所以协程就是为了解决这个问题出现。 第一步:在模块级的build.gradle中引入 id com.android.application// roomid kotlin-androidid kotlin…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...

最新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采用统一的扩散架构…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...