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/716592.shtml

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

相关文章

sql注入之sqli-labs-less-1 错误注入

输入?id1 得到登录页面&#xff1a; 通过order by 函数试探&#xff1a; 5的时候报错 试探到3 的时候返回正确的值&#xff1a; 然后继续注入&#xff1a;?id -1 union select 1,2,3 -- 查看回显点&#xff1a; 开始查看数据库内容&#xff1a;id-1 union select 1,databa…

open-spider开源爬虫工具:抖音数据采集

在当今信息爆炸的时代&#xff0c;网络爬虫作为一种自动化的数据收集工具&#xff0c;其重要性不言而喻。它能够帮助我们从互联网上高效地提取和处理数据&#xff0c;为数据分析、市场研究、内容监控等领域提供支持。抖音作为一个全球性的短视频平台&#xff0c;拥有海量的用户…

CKA考生注意:这些Deployment要点能助你一臂之力!

往期精彩文章 : 提升CKA考试胜算&#xff1a;一文带你全面了解RBAC权限控制&#xff01;揭秘高效运维&#xff1a;如何用kubectl top命令实时监控K8s资源使用情况&#xff1f;CKA认证必备&#xff1a;掌握k8s网络策略的关键要点提高CKA认证成功率&#xff0c;CKA真题中的节点维…

68-解构赋值,迭代器,生成器函数

1.解构赋值(针对数组array&#xff0c;字符串String及对象object以) 结构赋值是一种特殊的语法&#xff0c;通过将各种结构中的元素复制到变量中达到"解构"的目的&#xff0c;但是数组本身没有改变 1.1解构单层数组 <script>let arr [1,2,3,4,5];//获取数组…

c++ primer学习笔记(一)

目录 第一章、c快速入门 重点&#xff1a;类的简介 第二章 1、基本内置类型 2、字面值常量 1、整型字面值规则 2、浮点字面值规则 3、布尔字面值 4、字符字面值 5、非打印字符的转义序列 ​编辑 6、字符串字面值 3、变量 1、变量标识符 2、定义和初始化对象 3、…

java: 无法访问org.springframework.web.bind.annotation.RequestMapping......类文件具有错误的版本 61.0, 应为 52.0

文章目录 一、报错问题二、问题背景三、原因分析四、解决方案 一、报错问题 java: 无法访问org.springframework.web.bind.annotation.RequestMapping 错误的类文件: /D:/SoftwareInstall/Maven/repository/org/springframework/spring-web/6.0.9/spring-web-6.0.9.jar!/org/s…

latex报错Repeated entry解决办法

报错原因——重复了两个参考文献&#xff0c;删掉一个即可 总结 "Repeated entry"这个错误通常出现在你尝试在LaTeX中多次使用同一个标签&#xff08;label&#xff09;或者多次插入相同的图像/表格等时。例如&#xff0c;在LaTeX中&#xff0c;我们可能会为每一个章…

Modern C++ std::any为何要求Tp可拷贝构造?

小问题也会影响设计的思路&#xff0c;某个问题或某种case的探讨有助于理解设计的初衷。 声明&#xff1a;以下_Tp/Tp都是指要放入std::any的对象的类型。 它要求_Tp is_copy_constructible, 仅仅是因为有很多函数的实现调用了Tp的拷贝构造函数吗&#xff1f;比如说上节提到的初…

动态SQL的处理

学习视频&#xff1a;3001 动态SQL中的元素_哔哩哔哩_bilibili 目录 1.1为什么学 1.2动态SQL中的元素 条件查询操作 if 元素 choose、when、otherwise元素 where、trim元素 更新操作 set元素使用场景 复杂查询操作 foreach 元素中的属性 ​编辑 迭代数组 迭代List 迭代Map 1…

第3部分 原理篇2去中心化数字身份标识符(DID)(4)

3.2.3. DID解析 3.2.3.1. DID解析参与方 图3-5 DID 解析过程 本聪老师&#xff1a;我们之前提到过&#xff0c;DID 解析过程是将 DID 转换为对应的 DID 文档。这样做的目的是验证 DID 所代表的主体的身份。那么解析过程会涉及哪些概念呢&#xff1f;我们看图3-&#xff0c;DI…

端智能:面向手机计算环境的端云协同AI技术创新

近年来&#xff0c;随着移动端设备软硬件能力的进步&#xff0c;移动端的算力有了很大提升&#xff0c;同时面向移动端的机器学习框架和模型轻量化技术越来越成熟&#xff0c;端上的AI能力逐渐进入大众视野&#xff0c;端智能在电商领域也开始逐步走向规模化应用。通过持续探索…

leetcode日记(35)跳跃游戏Ⅱ

想了一个晚上&#xff0c;第一个思路是用动态规划&#xff0c;记录走到每一个节点需要跳动的最小步数&#xff0c;大致方法是每走到一个节点就遍历一下前面的全部节点&#xff0c;看看哪个节点可以一部跳到该节点&#xff0c;然后从中选取跳跃步数最小的节点&#xff0c;最后输…

基于springboot+vue的城镇保障性住房管理系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

练习 3 Web [ACTF2020 新生赛]Upload

[ACTF2020 新生赛]Upload1 中间有上传文件的地方&#xff0c;试一下一句话木马 txt 不让传txt 另存为tlyjpg&#xff0c;木马文件上传成功 给出了存放目录&#xff1a; Upload Success! Look here~ ./uplo4d/06a9d80f64fded1e542a95e6d530c70a.jpg 下一步尝试改木马文件后缀…

从头构建gpt2 基于Transformer

从头构建gpt2 基于Transformer VX关注{晓理紫|小李子}&#xff0c;获取技术推送信息&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持&#xff01;&#xff01; 如果你感觉对你有所帮助&#xff0c;请关注我。 源码获取 VX关注晓理紫并回复“chatgpt…

CSS 自测题

盒模型的宽度计算 默认为标准盒模型 box-sizing:content-box; offsetWidth (内容宽度内边距 边框)&#xff0c;无外边距 答案 122px通过 box-sizing: border-box; 可切换为 IE盒模型 offsetWidth width 即 100px margin 纵向重叠 相邻元素的 margin-top 和 margin-bottom 会发…

Benchmark学习笔记

小记一篇Benchmark的学习笔记 1.什么是benchmark 在维基百科中&#xff0c;是这样子讲的 “As computer architecture advanced, it became more difficult to compare the performance of various computer systems simply by looking at their specifications.Therefore, te…

python标识符、变量和常量

一、保留字与标识符 1.1保留字 保留字是指python中被赋予特定意义的单词&#xff0c;在开发程序时&#xff0c;不可以把这些保留字作为变量、函数、类、模块和其它对象的名称来使用。 比如&#xff1a;and、as、def、if、import、class、finally、with等 查询这些关键字的方…

【LeetCode】升级打怪之路 Day 11 加餐:单调队列

今日题目&#xff1a; 239. 滑动窗口最大值 | LeetCode 今天学习了单调队列这种特殊的数据结构&#xff0c;思路很新颖&#xff0c;值得学习。 Problem&#xff1a;单调队列 【必会】 与单调栈类似&#xff0c;单调队列也是一种特殊的数据结构&#xff0c;它相比与普通的 que…

【NR 定位】3GPP NR Positioning 5G定位标准解读(一)

目录 前言 1. 3GPP规划下的5G技术演进 2. 5G NR定位技术的发展 2.1 Rel-16首次对基于5G的定位技术进行标准化 2.2 Rel-17进一步提升5G定位技术的性能 3. Rel-18 关于5G定位技术的新方向、新进展 3.1 Sidelink高精度定位功能 3.2 针对上述不同用例&#xff0c;3GPP考虑按…