数据库之MyBatisPlus详解

MyBatisPlus

image.png

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window) 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

官网地址:https://baomidou.com/

一、入门案例

1.准备表结构和数据

  准备如下的表结构和相关数据

DROP TABLE IF EXISTS user;CREATE TABLE user
(id BIGINT(20) NOT NULL COMMENT '主键ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年龄',email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (id)
);

插入对应的相关数据

DELETE FROM user;INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

2. 创建项目

  创建一个SpringBoot项目,然后引入相关的依赖,首先是父依赖

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.6</version><relativePath/> <!-- lookup parent from repository --></parent>

具体的其他的依赖

<!-- spring-boot-starter-web 的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- 引入MyBatisPlus的依赖 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><!-- 数据库使用MySQL数据库 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- 数据库连接池 Druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.14</version></dependency><!-- lombok依赖 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>

3.配置信息

  然后我们需要在application.properties中配置数据源的相关信息

spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mp?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

然后我们需要在SpringBoot项目的启动类上配置Mapper接口的扫描路径

image.png

4.添加User实体

  添加user的实体类

@ToString
@Data
public class User {private Long id;private String name;private Integer age;private String email;
}

5.创建Mapper接口

  在MyBatisPlus中的Mapper接口需要继承BaseMapper.

/*** MyBatisPlus中的Mapper接口继承自BaseMapper*/
public interface UserMapper extends BaseMapper<User> {
}

6.测试操作

  然后来完成对User表中数据的查询操作

@SpringBootTest
class MpDemo01ApplicationTests {@Autowiredprivate UserMapper userMapper;@Testvoid queryUser() {List<User> users = userMapper.selectList(null);for (User user : users) {System.out.println(user);}}}

image.png

7.日志输出

  为了便于学习我们可以指定日志的实现StdOutImpl来处理

# 指定日志输出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

image.png

然后操作数据库的时候就可以看到对应的日志信息了:

image.png

二、CRUD操作

1.插入用户

  先来看看插入用户的操作,在MyBatisPlus中给我们提供一个insert()方法来实现。

    /*** 添加用户信息*/@Testvoid addUser() {User user = new User(null, "zs", 18, "123@qq.com");int i = userMapper.insert(user);System.out.println("i = " + i);}

插入成功后生成的id是一长串数字:

image.png

注意:在MyBatisPlus中插入数据的时候,如果id为空,默认会通过雪花算法来生成id

2.更新用户

  然后来看看MyBatisPlus中的更新操作。

    /*** 更新用户信息*/@Testvoid updateUser() {User user = new User(6l, "zs", 20, "123@qq.com");int i = userMapper.updateById(user);}

3.删除用户

  删除用户的方法在MyBatisPLUS中提供的有多个

3.1 根据id删除

    @Testvoid deleteUser() {User user = new User(6l, "zs", 20, "123@qq.com");userMapper.deleteById(6l);}

3.2 批量删除

  MyBatisPlus中也支持批量删除的操作

    /*** 批量删除*/@Testvoid deleteBathUser() {int i = userMapper.deleteBatchIds(Arrays.asList(1l, 2l, 3l, 4l));System.out.println("受影响的行数:" + i);}

3.3 通过Map删除

根据 columnMap 条件,删除记录

    /*** 根据 columnMap 条件,删除记录*/@Testvoid deleteMapUser() {Map<String,Object> map = new HashMap<>();map.put("age",18);map.put("name","tom");int i = userMapper.deleteByMap(map);System.out.println("受影响的行数:" + i);}

4.查询操作

4.1 根据id查询

  首先我们可以根据id来查询单条记录

    @Testvoid queryUserById() {User user = userMapper.selectById(1l);System.out.println(user);}

4.2 根据id批量查询

  然后也可以通过类似于SQL语句中的in关键字来实现多id的查询

    @Testvoid queryUserByBatchId() {List<User> users = userMapper.selectBatchIds(Arrays.asList(1l, 2l, 3l));users.forEach(System.out::println);}

4.3 通过Map查询

  也可以把需要查询的字段条件封装到一个Map中来查询

    @Testvoid queryUserByMap() {Map<String,Object> map = new HashMap<>();map.put("age",18);map.put("name","tom");List<User> users = userMapper.selectByMap(map);users.forEach(System.out::println);}

4.4 查询所有数据

  也可以通过selectList方法来查询所有的数据

    /*** 查询用户信息*/@Testvoid queryUser() {List<User> users = userMapper.selectList(null);for (User user : users) {System.out.println(user);}}

当然在selectList中需要我们传递进去一个Wrapper对象,这个是一个条件构造器,这个在后面会详细的讲解。

三、CRUD接口

官网地址:https://baomidou.com/pages/49cc81/#service-crud-%E6%8E%A5%E5%8F%A3

官网说明:

  • 通用 Service CRUD 封装IService(opens new window)接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,
  • 泛型 T 为任意实体对象
  • 建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类
  • 对象 Wrapper 为 条件构造器

在MyBatis-Plus中有一个接口 IService和其实现类 ServiceImpl,封装了常见的业务层逻辑

1.Service的使用

  要使用CRUD的接口,那么我们自定义的Service接口需要继承IService接口。

/*** User对应的Service接口* 要使用MyBatisPlus的Service完成CRUD操作,得继承IService*/
public interface IUserService extends IService<User> {
}

对应的Service实现得继承ServiceImpl同时指定mapper和实体对象。

/*** Service的实现类* 必须继承ServiceImpl 并且在泛型中指定 对应的Mapper和实体对象*/
@Service
public class UserService extends ServiceImpl<UserMapper, User> implements IUserService {
}

2.查询操作

  通过Service中提供的count方法可以查询总的记录数。get方法,List方法等

    @Autowiredprivate IUserService userService;@Testvoid getUserCount() {long count = userService.count();System.out.println("count = " + count);}

3.批量插入

  在service中给我们提供了批量插入的方法

    @Testvoid saveBatchUser() {List<User> list = new ArrayList<>();for (int i = 0; i < 10; i++) {User user = new User(null,"a"+i,10+i,"aaa@163.com");list.add(user);}// 批量插入userService.saveBatch(list);// batchSize:50// userService.saveBatch(list,50);}

还有saveOrUpdate等方法,可自行应用。

四、常用注解

1.@TableName

经过以上的测试,在使用MyBatis-Plus实现基本的CRUD时,我们并没有指定要操作的表,只是在
Mapper接口继承BaseMapper时,设置了泛型User,而操作的表为user表
由此得出结论,MyBatis-Plus在确定操作的表时,由BaseMapper的泛型决定,即实体类型决
定,且默认操作的表名和实体类型的类名一致

如果表名和我们的实体类的名称不一致的话,在执行相关操作的时候会抛出对应的异常,比如数据库的表我们该为T_USER,然后执行查询操作。

image.png

这时我们就可以通过@TableName来解决这个问题。

/*** @TableName 标识实体类对应的表名*/
@TableName("t_user")
@AllArgsConstructor
@ToString
@Data
public class User {private Long id;private String name;private Integer age;private String email;
}

  在开发的过程中,我们经常遇到以上的问题,即实体类所对应的表都有固定的前缀,例如t_或tbl_ 此时,可以使用MyBatis-Plus提供的全局配置,为实体类所对应的表名设置默认的前缀,那么就不需要在每个实体类上通过@TableName标识实体类对应的表.

# 指定日志输出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 配置MyBatis-Plus操作表的默认前缀
mybatis-plus.global-config.db-config.table-prefix=t_

2.@TableId

  我们可以通过@TableId注解来显示的指定哪个属性为主键对应的属性,在前面的例子中默认id就是,如果我们的主键字段不是id,比如uid的话,把实体user中的id改为uid,同时表结构中的id字段也修改为uid字段。我们来看看效果。执行插入操作。

image.png

  可以看到抛出了一个 Field 'uid' doesn't 的异常,这时我们可以在User实体的uid属性上添加@TableId即可。

image.png

  @TableId中的value值在实体类中的字段和表结构的字段一致的情况下我们不用添加,但如果不一致,@TableId中的value我们需要设置表结构中的主键字段。

image.png

@TableId中还有一个比较重要的属性是Type。Type是用来定义主键的生成策略的。以下是官网截图

image.png

这个可以在@TableId中配置,也可以在配置文件中统一配置全局的生成策略。

image.png

当然配置主键自增得在表结构中的字段要设置自动增长才行

image.png

3.@TableField

  @TableField注解的作用是当实体类中的属性和表结构中的字段名称不一致的情况下来设置对应关系的,当然,在MyBatis-Plus中针对实体中是userName而表结构中是user_name这种情况会自动帮助我们完成驼峰命名法的转换。

@AllArgsConstructor
@ToString
@Data
public class User {@TableId(value = "uid",type = IdType.ASSIGN_ID)private Long uid; // 表明uid就是主键字段对应的属性@TableField("name") // 表结构中的name属性和name属性对应private String name;private Integer age;private String email;
}

4.@TableLogic

  @TableLogic是用来完成 逻辑删除操作的

删除类型描述
逻辑删除假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,<br />之后在数据库中仍旧能看到此条数据记录
物理删除真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据

效果演示:先在表中创建一个is_deleted字段

image.png

对应的在实体类中添加一个isDeleted属性

image.png

然后我们调用删除功能

image.png

可以看到我们调用了deleteById方法,但是真实执行的是Update方法,实现了逻辑删除的场景。

当然也可以在属性文件中配置全局的

# 配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-field=is_deleted
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

五、条件构造器

  当我们需要对单表的CURD做复杂条件处理的时候我们就需要借助Wrapper接口来处理,也就是通过条件构造器来处理。

1.Wrapper接口

  Wrapper接口是条件构造的抽象类,是最顶级的类

image.png

对应的作用描述

image.png

2.QueryWrapper

  首先来看看QueryWrapper的使用,针对where后的条件封装。

2.1 查询条件

    /*** 查询用户姓名中包含 o 的年龄大于20岁,且邮箱不为null的记录*/@Testvoid queryUser() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.like("name","o").gt("age",20).isNotNull("email");List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);}

2.2 排序条件

  QueryWrapper也可以封装排序的条件

    /*** 根据年龄升序然后根据id降序*/@Testvoid queryUser() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.orderByAsc("age").orderByDesc("uid");List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);}

2.3 删除条件

  QueryWrapper也可以封装删除操作的条件

    /*** 删除所有年龄小于18岁的用户*/@Testvoid deleteUser() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.le("age",18);int i = userMapper.delete(wrapper);System.out.println(i);}

2.4 组合条件

  在封装条件的时候我们可以同时有多个条件组合,类似于 and 和 or的操作,这时QueryWrapper也能很轻松的处理。

    /*** 查询出年龄大于20并且姓名中包含的有'o'或者邮箱地址为空的记录*/@Testvoid queryUser() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.gt("age",20).like("name","o").or() // 默认是通过and连接 显示加上 or()方法表示or连接.isNotNull("email");List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);}@Testvoid queryUser1() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.and((i)->{i.gt("age",20).like("name","o");}).or((i)->{i.isNotNull("email");});List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);}

2.5 查询特定的字段

  特殊情况我们需要查询特定的字段,这时可以通过select方法来处理

    /*** 查询出年龄大于20并且姓名中包含的有'o'或者邮箱地址为空的记录*/@Testvoid queryUser() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.gt("age",20).like("name","o").or() // 默认是通过and连接 显示加上 or()方法表示or连接.isNotNull("email").select("uid","name","age") // 指定特定的字段;//selectMaps()返回Map集合列表,通常配合select()使用,避免User对象中没有被查询到的列值为nullList<Map<String, Object>> maps = userMapper.selectMaps(wrapper);maps.forEach(System.out::println);}

2.6 实现子查询

  单表查询中对子查询的需求也是有的,我们来看看如何实现。

    /*** 子查询* SELECT uid,name,age,email,is_deleted * FROM t_user * WHERE ( *          uid IN (select uid from t_user where uid < 5)*      )*/@Testvoid queryUser() {QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.inSql("uid","select uid from t_user where uid < 5");List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);maps.forEach(System.out::println);}

3.UpdateWrapper

  当我们需要组装更新的字段数据的时候,可以通过UpdateWrapper来实现。

    /*** 更新用户Tom的age和邮箱信息* UPDATE t_user SET age=?,email=? WHERE (name = ?)*/@Testvoid updateUser() {UpdateWrapper<User> wrapper = new UpdateWrapper<>();wrapper.set("age",25).set("email","bobo@qq.com").eq("name","Tom");int update = userMapper.update(null, wrapper);System.out.println("update = " + update);}

4.动态SQL

  实际开发中,用户的查询条件都是动态的,我们需要根据不同的输入条件来动态的生成对应的SQL语句,这时我们来看看在MyBatisPlus中是如何处理的。

    @Testvoid queryUser1() {String  name = "Tom";Integer age = null;String email = null;QueryWrapper<User> wrapper = new QueryWrapper<>();if(!StringUtils.isEmpty(name)){wrapper.eq("name",name);}if(age != null && age > 0){wrapper.eq("age",age);}if(!StringUtils.isEmpty(email)){wrapper.eq("email",email);}List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);}

上面的代码是通过if来一个个判断的,看起来代码比较复杂,其实大家在前面看相关的API的时候会注意到都会有一个Condition参数

image.png

我们可以用这个参数来实现对应的动态SQL处理

    @Testvoid queryUser2() {String  name = "Tom";Integer age = null;String email = null;QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq(StringUtils.isNotBlank(name),"name",name).eq(age!=null && age > 0 ,"age" ,age).eq(StringUtils.isNotBlank(email),"email",email);List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);}

六、分页插件

  在MyBatisPlus中集成了分页插件,我们不需要单独的引入,只需要添加对应的配置类

@Configuration
@MapperScan("com.bobo.mpdemo01.mapper")
public class MyBatisPlusConfig {/*** 新的分页插件,一缓和二缓遵循mybatis的规则,* 需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}}

然后就可以测试操作了

    @Testvoid queryPage() {Page<User> page = new Page<>(1,5);Page<User> userPage = userMapper.selectPage(page, null);System.out.println("userPage.getCurrent() = " + userPage.getCurrent());System.out.println("userPage.getSize() = " + userPage.getSize());System.out.println("userPage.getTotal() = " + userPage.getTotal());System.out.println("userPage.getPages() = " + userPage.getPages());System.out.println("userPage.hasPrevious() = " + userPage.hasPrevious());System.out.println("userPage.hasNext() = " + userPage.hasNext());}

七、代码生成器

添加依赖

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.5.2</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId></dependency>

快速生成:

/*** 代码生成器*/
public class MyFastAutoGenerator {public static void main(String[] args) {FastAutoGenerator.create("jdbc:mysql://localhost:3306/mp?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true", "root", "123456").globalConfig(builder -> {builder.author("boge") // 设置作者//.enableSwagger() // 开启 swagger 模式.fileOverride() // 覆盖已生成文件.outputDir("D://MyBatisPlus"); // 指定输出目录}).packageConfig(builder -> {builder.parent("com.bobo.mp") // 设置父包名.moduleName("system") // 设置父包模块名.pathInfo(Collections.singletonMap(OutputFile.xml, "D://")); // 设置mapperXml生成路径}).strategyConfig(builder -> {builder.addInclude("t_user") // 设置需要生成的表名.addTablePrefix("t_", "c_"); // 设置过滤表前缀}).templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板.execute();}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/782771.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++学习随笔(8)——模板初阶

本章我们来学习一下C的模版部分&#xff01; 目录 1. 泛型编程 2. 函数模板 2.1 函数模板概念 2.1 函数模板格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 3. 类模板 3.1 类模板的定义格式 3.2 类模板的实例化 1. 泛型编程 如何实现一个通…

精通Go语言文件上传:深入探讨r.FormFile函数的应用与优化

1. 介绍 1.1 概述 在 Web 开发中&#xff0c;文件上传是一项常见的功能需求&#xff0c;用于允许用户向服务器提交文件&#xff0c;如图像、文档、视频等。Go 语言作为一门强大的服务器端编程语言&#xff0c;提供了方便且高效的方式来处理文件上传操作。其中&#xff0c;r.F…

(完结)Java项目实战笔记--基于SpringBoot3.0开发仿12306高并发售票系统--(三)项目优化

本文参考自 Springboot3微服务实战12306高性能售票系统 - 慕课网 (imooc.com) 本文是仿12306项目实战第&#xff08;三&#xff09;章——项目优化&#xff0c;本篇将讲解该项目最后的优化部分以及一些压测知识点 本章目录 一、压力测试-高并发优化前后的性能对比1.压力测试相关…

探索C语言中的联合体和枚举:让处理数据更加得心应手

✨✨小新课堂开课了&#xff0c;欢迎欢迎~✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;http://t.csdnimg.cn/Oytke 小新的主页&#xff1a;编程版小新-CSDN博客 C语言中有内置类型&#xff0c; 比如&…

2024年云计算使用报告,89%组织用多云,25%广泛使用生成式AI,45%需要跨云数据集成,节省成本是云首要因素

备注&#xff1a;本文来自Flexera2024年的云现状调研报告的翻译。原报告地址&#xff1a; https://info.flexera.com/CM-REPORT-State-of-the-Cloud Flexera是一家专注于做SaaS的IT解决方案公司&#xff0c;有30年发展历史&#xff0c;5万名客户&#xff0c;1300名员工。Flex…

​数据结构—栈操作经典案例

括号匹配&#xff1a; 这是我最开始写的&#xff0c;运行有问题 对于输入的括号序列&#xff0c;建议使用标准的 C 字符串而不是字符数组。 #include<iostream> using namespace std;typedef char SelemType; typedef int Status; #define OK 1 #define MAXSIZE 100 #…

python基础——异常捕获【try-except、else、finally】

&#x1f4dd;前言&#xff1a; 这篇文章主要介绍一下python基础中的异常处理&#xff1a; 1&#xff0c;异常 2&#xff0c;异常的捕获 3&#xff0c;finally语句 &#x1f3ac;个人简介&#xff1a;努力学习ing &#x1f4cb;个人专栏&#xff1a;C语言入门基础以及python入门…

【C++】右值引用

目录 前言&#xff1a;一、左值引用和右值引用1.1 什么是左值和左值引用1.2 什么是右值和右值引用 二、左值引用和右值引用比较三、右值引用使用场景3.1 传值返回使用场景3.2 移动构造3.3 移动赋值3.4 STL容器接口也增加右值引用3.5 完美转发 前言&#xff1a; 引用是给对象取…

HarmonyOS 应用开发之模型切换

本文介绍如何将一个FA模型开发的声明式范式应用切换到Stage模型&#xff0c;您需要完成如下动作&#xff1a; 工程切换&#xff1a;新建一个Stage模型的应用工程。 配置文件切换&#xff1a;config.json切换为app.json5和module.json5。 组件切换&#xff1a;PageAbility/Serv…

不同的batch_size对精度和损失的影响研究

1 问题 不同的batch_size对训练集和验证集的精度和损失的影响有多大&#xff1f; 2 方法 通过设置不同batch_size算出不同batch_size对应的训练集精度、训练集损失和验证集的精度和损失&#xff0c;通过数据可视化将精度和损失展示出来&#xff0c;比较出不同batch_size对他们的…

CTK插件框架学习-插件注册调用(03)

CTK插件框架学习-新建插件(02)https://mp.csdn.net/mp_blog/creation/editor/136923735 一、CTK插件组成 接口类&#xff1a;对外暴露的接口&#xff0c;供其他插件调用实现类&#xff1a;实现接口内的方法激活类&#xff1a;负责将插件注册到CTK框架中 二、接口、插件、服务…

文生视频大模型Sora的复现经验

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

BFS专题

1、BFS解决FloodFill算法 1、1图像渲染 733. 图像渲染 - 力扣(LeetCode) class Solution {typedef pair<int,int> PII;int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0}; public:vector<vector<int>> floodFill(vector<vector<int>>& i…

RIP环境下的MGRE 综合实验

实验题目及要求&#xff1a; 1.R5为ISP&#xff0c;只能进行IP地址配置&#xff0c;其所有地址均配为公有IP地址 2.R1和R5间使用PPP的PAP认证&#xff0c;R5为主认证方; R2于R5之间使用PPP的chap认证&#xff0c;R5为主认证方&#xff1b; R3于R5之间使用HDLC封装。 3.R1/…

【C++】为什么能实现函数重载

从C语言一路学到C的途中&#xff0c;C语言C语言相比&#xff0c;多了个函数重载&#xff0c;那么函数重载是如何实现的呢&#xff0c;为什么C语言无法支持&#xff0c;在本篇博客中&#xff0c;将会讲解C为何能实现函数重载。 一.编译过程 C能实现函数重载&#xff0c;而C语言不…

QT 二维坐标系显示坐标点及点与点的连线-通过定时器自动添加随机数据点

QT 二维坐标系显示坐标点及点与点的连线-通过定时器自动添加随机数据点 功能介绍头文件C文件运行过程 功能介绍 上面的代码实现了一个简单的 Qt 应用程序&#xff0c;其功能包括&#xff1a; 创建一个 MainWindow 类&#xff0c;继承自 QMainWindow&#xff0c;作为应用程序的…

2024软件设计师备考讲义——UML(统一建模语言)

UML的概念 用例图的概念 包含 <<include>>扩展<<exted>>泛化 用例图&#xff08;也可称用例建模&#xff09;描述的是外部执行者&#xff08;Actor&#xff09;所理解的系统功能。用例图用于需求分析阶段&#xff0c;它的建立是系统开发者和用户反复…

Pyppeteer中Chromium安装步骤

1、下载压缩文件 在官网下载chrome-win.zip文件 2、终端下载pyppeteer 首先在Pycharm终端运行pip install pyppeteer 3、查找文件默认路径 在运行以下代码&#xff0c;找到可执行文件默认路径 import pyppeteer.chromium_downloader print(默认版本是&#xff1a;{}.forma…

牛角工具箱源码 轻松打造个性化在线工具箱

&#x1f389; Whats this&#xff1f; 这是一款在线工具箱程序&#xff0c;您可以通过安装扩展增强她的功能 通过插件模板的功能&#xff0c;您也可以把她当做网页导航来使用~ 觉得该项目不错的可以给个Star~ &#x1f63a; 演示地址 https://tool.aoaostar.com &#x1f…

TCP网络协议栈和Posix网络部分API总结

文章目录 Posix网络部分API综述TCP协议栈通信过程TCP三次握手和四次挥手&#xff08;看下图&#xff09;三次握手常见问题&#xff1f;为什么是三次握手而不是两次&#xff1f;三次握手和哪些函数有关&#xff1f;TCP的生命周期是从什么时候开始的&#xff1f; 四次挥手通信状态…