MybatisPlus

news/2024/4/25 0:26:18/

目录

  • MybatisPlus
    • 入门案例
      • 步骤
      • 代码实现
        • 数据库及表
        • MybatisPlus的Maven坐标
        • 配置数据库
        • 创建实体类
          • User
        • Mapper接口
          • UserMapper
        • 引导类
        • 测试类
    • 简介
    • 使用MP做标准数据层开发
      • 标准CRUD
        • 新增
        • 删除
        • 修改
        • 根据id查询
        • 查询所有
        • 分页查询
          • 步骤1:调用方法传入参数获取返回值
          • 步骤2:设置分页拦截器
      • DQL编程控制
        • 准备环境
          • application.yml
          • 引入依赖
          • logback.xml
        • 条件查询
        • 查询投影
        • 查询条件
      • 映射匹配兼容性
      • DML编程控制
        • id生成策略
        • 简化配置
        • 测试
        • 多记录操作
        • 逻辑删除
          • 测试
        • 乐观锁
          • 概念
          • 实现思路
          • 步骤

MybatisPlus

入门案例

步骤

  1. 创建数据库及表,导入数据
  2. 创建springboot项目,勾选实用技术,引入依赖
  3. 添加相关配置信息
  4. 编写实体类,创建mapper层接口
  5. 引导类添加mapper层接口扫描注解
  6. 编写测试类

代码实现

数据库及表

create database if not exists mybatisplus_db character set utf8;
use mybatisplus_db;
CREATE TABLE user (id bigint(20) primary key auto_increment,name varchar(32) not null,password  varchar(32) not null,age int(3) not null ,tel varchar(32) not null
);
insert into user values(1,'Tom','tom',3,'18866668888');
insert into user values(2,'Jerry','jerry',4,'16688886666');
insert into user values(3,'Jock','123456',41,'18812345678');
insert into user values(4,'传智播客','itcast',15,'4006184000');

MybatisPlus的Maven坐标

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version>
</dependency>

配置数据库

spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driver
#serverTimezone是用来设置时区,UTC是标准时区,和咱们的时间差8小时,所以可以将其修改为`Asia/Shanghaiurl: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=Asia/Shanghaiusername: rootpassword: root

创建实体类

User
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class User {private Long id;private String name;private String password;private Integer age;private String tel;private Integer online;
}

Mapper接口

UserMapper
public interface UserMapper extends BaseMapper<User> {
}

引导类

@SpringBootApplication
@MapperScan("com.shifan.mapper")//自动扫描该包下的所有接口
public class MybatisPlusApplication {public static void main(String[] args) {SpringApplication.run(MybatisPlusApplication.class, args);}}

测试类

@SpringBootTest
class MpApplicationTests {@Autowiredprivate UserDao userDao;@Testpublic void testGetAll() {List<User> userList = userDao.selectList(null);System.out.println(userList);}
}

简介

MyBatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率

官网:MybatisPlus

使用MP做标准数据层开发

标准CRUD

新增

int insert(T t)

    /*tips:爆红是因为UserMapper为接口,无法实例化实现注入服务器启动IOC容器初始化后,框架会生成代理对象完成注入*/@Autowiredprivate UserMapper userMapper;/*** int insert(T t)*/@Testvoid testSave() {User user = User.builder().name("时帆").age(18).password("111").tel("13511111111").build();userMapper.insert(user);}

删除

int deleteById(Serializable id)

    /*** int deleteById(Serializable id)*/@Testvoid testDeleteById(){userMapper.deleteById(2L);}

修改

int updateById(T t)

    /*** int updateById(T t)*/@Testvoid testUpdateById(){User user = User.builder().name("voracity").age(20).id(3L).password("333").build();userMapper.updateById(user);}

根据id查询

T selectById(Serializable id)

    /*** T selectById(Serializable id)*/@Testvoid testSelectById(){User user = userMapper.selectById(5L);System.out.println("user = " + user);}

查询所有

List selectList(Wrapper queryWrapper)

    /*** List<T> selectList(Wrapper<T> queryWrapper)*/@Testvoid testSelectList(){List<User> users = userMapper.selectList(null);System.out.println("users = " + users);}

分页查询

IPage selectPage(IPage page,Wrapper queryWrapper)

步骤1:调用方法传入参数获取返回值
    /*** IPage<T> selectPage(IPage<T> page , Wrapper<T> queryWrapper)*/@Testvoid testSelectPage(){//创建分页对象,设置分页参数,1为第一页,3为显示记录数IPage<User> page = new Page<>(1,3);userMapper.selectPage(page, null);//获取分页结果System.out.println("当前页码值:"+page.getCurrent());System.out.println("每页显示条数:"+page.getSize());System.out.println("一共多少页:"+page.getPages());System.out.println("一共多少条数据:"+page.getTotal());System.out.println("数据:"+page.getRecords());}
步骤2:设置分页拦截器

这个拦截器MP已经为我们提供好了,我们只需要将其配置成Spring管理的bean对象即可。

@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){//1 创建MybatisPlusInterceptor拦截器对象MybatisPlusInterceptor mpInterceptor=new MybatisPlusInterceptor();//2 添加分页拦截器mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());return mpInterceptor;}
}

DQL编程控制

准备环境

application.yml
spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driver
#serverTimezone是用来设置时区,UTC是标准时区,和咱们的时间差8小时,所以可以将其修改为`Asia/Shanghaiurl: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=Asia/Shanghaiusername: rootpassword: rootmain:#关闭springboot启动logbanner-mode: offmybatis-plus:configuration:# 开启mp日志输出到控制台,影响性能,调试用log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:#关闭mp启动log打印banner: off
引入依赖
    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.16</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version></dependency></dependencies>
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!--取消初始化spring日志打印,resources目录下添加logback.xml,名称固定-->
</configuration>

条件查询

  • Wrapper
    • QueryWrapper
    • LambdaQueryWrapper
@Autowiredprivate UserMapper userMapper;/*** 测试构建条件查询*/@Testvoid testGetAll() {/*方式一:lt表示小于,即条件为查询年龄小于30的数据缺点:字段名出错难以察觉*//*QueryWrapper qw = new QueryWrapper();qw.lt("age",30);List<User> users = userMapper.selectList(qw);System.out.println("users = " + users);*//*方式二:必须指定泛型,调用lambda()方法开启lambda表达式的使用缺点:多了一层.lambda()调用*//*QueryWrapper<User> qw = new QueryWrapper();qw.lambda().lt(User::getAge,30);List<User> users = userMapper.selectList(qw);System.out.println("users = " + users);*//*方式三:使用LambdaQueryWrapper类,不在需要调用lambda()*/LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();lqw.lt(User::getAge,30);List<User> users = userMapper.selectList(lqw);System.out.println("users = " + users);}
  • 多条件构建:or()

  • null值判定

/*** 测试构建多条件查询*/@Testvoid testGetAll1() {LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();//需求:查询年龄在10岁到30岁之间的用户信息//lqw.lt(User::getAge,30);//lqw.gt(User::getAge,10);//支持链式编程//lqw.lt(User::getAge,30).gt(User::getAge,10);//需求:查询年龄小于10或年龄大于30的数据//lqw.lt(User::getAge,10).or().gt(User::getAge,30);/*null值判定,多条件查询时,可能存在条件传递为null的情况需求:根据输入年龄范围来查询符合条件的记录(年龄上限,下限,可能不传递数据,即为null)传统解决方案:使用if语句判断*//*QueryUser qu = new QueryUser();qu.setAge(10);if (qu.getAge()!=null){lqw.gt(User::getAge,qu.getAge());}if (qu.getAge1()!=null){lqw.lt(User::getAge,qu.getAge1());}*//*MybatisPlus解决方案:*/QueryUser qu = new QueryUser();qu.setAge(10);lqw.gt(null!=qu.getAge(),User::getAge,qu.getAge());lqw.lt(null!=qu.getAge1(),User::getAge,qu.getAge1());List<User> users = userMapper.selectList(lqw);System.out.println("users = " + users);}

查询投影

  • 查询指定字段:select()
    /*** 查询投影*/@Testvoid testGetAll2() {LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();//需求:查询指定字段:id,name,age/*lqw.select(User::getId,User::getName,User::getAge);List<User> users = userMapper.selectList(lqw);*///若不使用lambda表达式,则需要手动设置字段QueryWrapper<User> qw = new QueryWrapper<>();qw.select("id","name","age");List<User> users = userMapper.selectList(qw);System.out.println("users = " + users);}
  • 聚合查询:eg:select(“count(id) count”)

  • 分组查询:eg:groupBy(User::getTel)

/*** 聚合函数查询* 聚合函数不支持lambda表达式,lambda表达式只支持实体类属性字段*/@Testvoid testGetAll3() {QueryWrapper<User> qw = new QueryWrapper<>();//qw.select("count(id) count");//加上分组条件qw.select("count(id) count ,tel").groupBy("tel");List<Map<String, Object>> maps = userMapper.selectMaps(qw);System.out.println("maps = " + maps);}@Testvoid test(){LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();lqw.select(User::getTel);lqw.groupBy(User::getTel);List<Map<String, Object>> users = userMapper.selectMaps(lqw);System.out.println("users = " + users);}

查询条件

  • 等值查询:eq()
    /*** 等值查询* 需求:根据用户名和密码查询用户信息* eq:相当于=*/@Testvoid testGetOne() {LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();lqw.eq(User::getName,"John");lqw.eq(User::getPassword,"shifan");User user = userMapper.selectOne(lqw);System.out.println("user = " + user);}
  • 范围查询:lt(),le(),gt(),ge(),between()
    /*** 范围查询* 需求:对年龄进行范围查询,使用lt()、le()、gt()、ge()、between()进行范围查询* le:相当于<=* ge:相当于>=*/@Testvoid testGetAll4(){LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();lqw.between(User::getAge,10,20);List<User> users = userMapper.selectList(lqw);System.out.println("users = " + users);}
  • 模糊查询:like(),likeLeft(),likeRight()
    /*** 模糊查询* 需求:查询表中name属性的值以`J`开头的用户信息,使用like进行模糊查询* like():在属性值字段的左右都加%,eg:lqw.like(User::getName,"J") ==> %J%* likeLeft():在属性值字段左边加%,eg:%J* likeRight():在属性值字段的右边加%,eg:J%*/@Testvoid testGetAll5() {LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();lqw.likeRight(User::getName,"J");List<User> users = userMapper.selectList(lqw);System.out.println("users = " + users);}
  • 排序查询:orderBy(),orderByAsc(),orderByDesc()
    /*** 排序查询* 需求:查询所有数据,然后按照id降序* orderBy(boolean condition, boolean isAsc, R... columns):* 第一个参数:是否排序,第二个参数:是否升序,true升序,false降序,第三个参数:字段名,可设置一个或多个* - orderByAsc/Desc(单个column):按照指定字段进行升序/降序* - orderByAsc/Desc(多个column):按照多个字段进行升序/降序* - orderByAsc/Desc*   - condition:条件,true添加排序,false不添加排序*   - 多个columns:按照多个字段进行排序* 此外还有isNull,isNotNull,in,notIn等方法*/@Testvoid testGetAll6() {LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();lqw.orderBy(true,false,User::getId);List<User> users = userMapper.selectList(lqw);System.out.println("users = " + users);}

映射匹配兼容性

  • @TableField(value=“表字段名”)

  • @TableField(select = false)

  • @TableField(exist = false)

  • @TableName(“表名”)

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_user")//映射数据库表名,用于数据库表名和实体类名不一致情况
public class User {private Long id;private String name;@TableField(value = "pwd",select = false)//字段映射,value属性为数据库表中字段名,selcet属性用于设置该字段是否被查询private String password;private Integer age;private String tel;@TableField(exist = false)//exist属性用于表明该字段在数据库表中是否存在private Integer online;
}

DML编程控制

id生成策略

  • @TableId(type = IdType.NONE)

NONE表示不使用id生成策略,与INPUT类似,需要手动注入id

  • @TableId(type = IdType.AUTO)

AUTO表示使用数据库的主键id自增,前提是数据库的主键id设置了自增属性

  • @TableId(type = IdType.INPUT)

INPUT表示id使用手动注入的方式

  • @TableId(type = IdType.ASSIGN_ID)

ASSIGN_ID表示使用MP的雪花算法生成id

  • @TableId(type = IdType.ASSIGN_UUID)

ASSIGN_UUID表示使用UUID生成id

实际使用案例:

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
//@TableName("tb_user")//映射数据库表名,用于数据库表名和实体类名不一致情况
public class User {//@TableId(type = IdType.NONE)// 不使用主键生成策略,类似Input//@TableId(type= IdType.AUTO)// 使用数据库主键自增,需要保证数据库主键字段有自增属性//@TableId(type = IdType.Input)// 用户手动输入,需要去除数据库主键自增属性,若不给定id值会报错//@TableId(type = IdType.ASSIGN_UUID)// 使用UUID生成主键id,主键类型应为字符串,数据库表中id长度至少32位,长度过小会插入失败//@TableId(type = IdType.ASSIGN_ID)// 使用雪花算法生成主键id(可兼容数值型与字符串型),若所传递的id为null,默认使用此策略,若传递了值则使用传递的值private Long id;private String name;@TableField(value = "pwd",select = false)//字段映射,value属性为数据库表中字段名,selcet属性用于设置该字段是否被查询private String password;private Integer age;private String tel;@TableField(exist = false)//exist属性用于表明该字段在数据库表中是否存在private Integer online;}

简化配置

在配置文件中添加如下配置即可实现全局使用雪花算法生成id

mybatis-plus:global-config:db-config:id-type: assign_id

以下配置用于配置全局表名前缀

mybatis-plus:global-config:db-config:table-prefix: tbl_

测试

/*** 测试主键自增策略* 拓展:分布式id* 当数据量足够大时就需要将数据存储在多台数据库服务器上* 例如订单表存储在不同服务器上,而此时主键若使用自增策略就可能出现冲突* 这时就需要一个全局唯一的id,称为分布式id** 雪花算法:* 雪花算法(SnowFlake),是Twitter官方给出的算法实现 是用Scala写的。* 其生成的结果是一个64bit大小整数,它的结构分为四部分,如下:* 0-00000000 00000000 00000000 00000000 00000000 0-00000000 00-00000000 0000* 第一部分: 1bit,不用,因为二进制中最高位是符号位,1表示负数,0表示正数。生成的id一般都是用整数,所以最高位固定为0。* 第二部分: 41bit-时间戳,用来记录时间戳,毫秒级* 第三部分: 10bit-工作机器id,用来记录工作机器id,其中高位5bit是数据中心ID其取值范围0-31,低位5bit是工作节点ID其取值范围0-31,两个组合起来最多可以容纳1024个节点* 第四部分: 序列号占用12bit,每个节点每毫秒从0开始不断累加,最多可以累加到4095,每毫秒内一共可以产生4096个ID* id生成策略对比:* - NONE: 不设置id生成策略,MP不自动生成,约等于INPUT,所以这两种方式都需要用户手动设置,但是手动设置第一个问题是容易出现相同的ID造成主键冲突,为了保证主键不冲突就需要做很多判定,实现起来比较复杂* - AUTO:数据库ID自增,这种策略适合在数据库服务器只有1台的情况下使用,不可作为分布式ID使用* - ASSIGN_UUID:可以在分布式的情况下使用,而且能够保证唯一,但是生成的主键是32位的字符串,长度过长占用空间而且还不能排序,查询性能也慢* - ASSIGN_ID:可以在分布式的情况下使用,生成的是Long类型的数字,可以排序性能也高,但是生成的策略和服务器时间有关,如果修改了系统时间就有可能导致出现重复主键* 综上:根据实际情况选择*/@Testvoid testInsert(){User user = User.builder().name("xiaoming").age(23).tel("12345678345").password("333").build();userMapper.insert(user);}

多记录操作

需求:批量删除用户数据,批量查询用户数据

测试如下:

/*** 测试批量删除*/@Testvoid testDeleteByIds(){List<Long> list = new ArrayList<>();list.add(1647447562652774401L);list.add(1647452538326233089L);list.add(1647452707453181954L);userMapper.deleteBatchIds(list);}/*** 测试批量查询*/@Testvoid testSelectByIds(){List<Long> list = new ArrayList<>();list.add(1L);list.add(3L);list.add(4L);List<User> users = userMapper.selectBatchIds(list);System.out.println("users = " + users);}

逻辑删除

  • @TableLogic

实现步骤:

  1. 在数据库表中添加标识逻辑删除的字段
  2. 在实体类中添加对应的标识字段,并在此字段上添加@TableLogic注解
  3. 设置@TableLogic的value和delval属性值,value属性表示当前数据为正常数据,delval属性表示当前数据为
    已被删除的数据

实际应用:

    //@TableLogic(value = "0",delval = "1")//逻辑删除字段,标记当前数据是否被删除,value表示正常数据,delval表示该数据已被删除private Integer deleted;

全局配置:

mybatis-plus:global-config:db-config:# 逻辑删除字段名logic-delete-field: deleted# 逻辑删除字面值:未删除为0logic-not-delete-value: 0# 逻辑删除字面值:删除为1logic-delete-value: 1
测试
/*** 测试逻辑删除* 用途:解决物理删除(直接删除表中数据,delete操作)会对数据造成伤害的问题* 步骤:在表中添加一个字段(添加默认值属性),用于标识当前数据是否被删除* 在实体类中添加对应的字段并使用@TableLogic注解标识该字段,给定value和delval属性的值即可* 逻辑删除本质上执行的是更新语句,配置了逻辑删除字段后,查询也会自动带上该字段,只查询未被删除的数据* 若需要查询已被删除的数据则需要自己手写实现*/@Testvoid testLogicDelete(){userMapper.deleteById(1L);List<User> users = userMapper.selectList(null);System.out.println("users = " + users);}

乐观锁

概念

主要用于解决修改数据时,期望当前数据未被其他人修改

实现思路
步骤
/*** 乐观锁测试* 原理:* 给数据库表添加字段,如version默认值为1* 当两个线程同时修该一条数据时,需要先获取表中数据,拿到version的值* eg:线程A和B同时来修改id为1的用户的信息* 线程A查询id为1的用户信息,得到此时用户的version字段值为1* 线程B同样查询到id为1的用户信息,此时用户的version字段值为1* 假设线程B先于线程A修改了id为1的用户的信息,并将version的值加了1* 即:update user set name = ? , age = ? ,version = version + 1 where id = 1 and version = 1* 此时线程A再去修改用户信息时就会修改失败,因其修改语句为:* update user set name = ? , age = ? ,version = version + 1 where id = 1 and version = 1* 而version值已被修改为2,故修改失败* 实现步骤:* 1.在数据库表中添加标识字段,并设置默认值,eg:version字段,默认值1* 2.在实体类中添加对应的属性字段,并加上注解@Version* 3.添加乐观锁拦截器* 4.查询需要修改的数据,获取version值* 5.更改数据值,更新数据*/@Testvoid testOptimisticLock(){//没有设置version值,无法实现乐观锁/*User user = User.builder().id(3L).name("mp").password("399").tel("322").age(10).build();*///先查询需要修改的数据User user = userMapper.selectById(3L);//修改数据user.setName("mp");user.setAge(10);user.setPassword("3");//更新数据userMapper.updateById(user);}/*** 模拟多线程情况修改同一条数据*/@Testvoid testOptimisticLock1(){//先查询需要修改的数据User user = userMapper.selectById(3L);//取得的version值为2User user1 = userMapper.selectById(3L);//取得的version值为2user1.setName("user1");userMapper.updateById(user1);//修改成功,version->3user.setName("user");userMapper.updateById(user);//修改失败,此时version值已被修改为3}

http://www.ppmy.cn/news/47062.html

相关文章

2023/4/18往日题目总结

搜索路径状态记录 1076. 迷宫问题 - AcWing题库 //以最简单的迷宫问题为例&#xff0c;如何记录走迷宫的路径&#xff0c;其实只需要记录一下状态即可 //也就是记录一下这个点是从哪个点来的&#xff0c;最后从终点开始输出即可&#xff08;此时输出的是逆序&#xff09; #in…

flowable流程图绘制工具flowable-ui的安装和使用

一.简介 记录绘制flowable图的过程。 二.下载安装 1.下载 我这边是windows的&#xff0c;下载的版本是6.8.0&#xff0c;zip那个就可以&#xff0c;tar.gz是linux的 下载地址&#xff1a;https://github.com/flowable/flowable-engine/releases/tag/flowable-6.8.0 下载截…

pyecharts从入门到精通-地图专题Map-带时间轴与网格的复杂绘图

文章目录 参考安装与查看pyecharts地图实现-Geo导入依赖生成数据集生成2013-2018年的各个省份GDP数据生成2013-2018年的时间列表生成2013-2018年的总GDP设置visulmap的最大最小值范围 生成2013年的网格组合图提取2013年的数据测试绘制map地图绘制折线图line绘制折线图bar绘制折…

ChatGPT/大模型+零代码,给中小企业带来哪些机会?

ChatGPT让2023年成了AI之年。正如iPhone在2007年开启了智能手机时代&#xff0c;我们现在正在进入人工智能时代。 新形势下&#xff0c;零代码应如何借势发力&#xff1f;伙伴云“AI零代码”给出了答案。 作为零代码领域的头部平台&#xff0c;伙伴云全量发布【AI零代码应用搭…

第四十章 文本渲染总结(未完结)

OpenGL本身没有包含任何的文本处理能力,需要自己定义一套全新的系统让OpenGL绘制文本到屏幕上,但是文本字符没有图元。 可以通过GL_LINES来绘制自行,创建文本的3D网格,或者是将3D环境中字符纹理渲染到2D四边形上。 常用的方法是:将字符纹理绘制到四边形上。 经典文本渲染…

手势控制的机器人手臂

将向你展示如何构建机械手臂并使用手势和计算机视觉来控制它。下面有一个在开发阶段的机械手臂的演示视频。 展示开发中的手臂的演示视频&#xff1a;https://youtu.be/KwiwetZGv0s 如图所示&#xff0c;该过程首先用摄像头捕捉我的手及其标志。通过跟踪特定的界标&#xff0c;…

(7)(7.5) 电机推力比例

文章目录 前言 1 推力曲线 2 推力支架 3 参数计算 前言 Copter 包括电机推力比例,补偿了大多数电调和电机的非线性推力输出。

短轮询、长轮询、SSE 和 WebSocket 间的区别

即时通讯的实现&#xff1a;短轮询、长轮询、SSE 和 WebSocket 间的区别 学习内容&#xff1a; 短轮询&#xff1a;短轮询是一种客户端与服务器之间的通讯方式&#xff0c;客户端定期向服务器发送请求&#xff0c;以检查是否有新消息。如果没有新消息&#xff0c;服务器会返回…

迷宫问题-DFS-BFS

迷宫问题 迷宫问题简介BFS解决迷宫最短路径问题DFS记录迷宫路径DFS解决迷宫所有路径问题 迷宫问题简介 &#x1f680;学习过算法程序设计的应该都学习过迷宫这个问题&#xff0c;迷宫问题主要设计的算法就是DFS-深度优先遍历和BFS-广度优先遍历。 &#x1f680;在一个二维数组…

gpt4all保姆级使用教程! 不用联网! 本地就能跑的GPT

原文&#xff1a;gpt4all保姆级使用教程! 不用联网! 本地就能跑的GPT 什么是gpt4all gpt4all是在大量干净数据上训练的一个开源聊天机器人的生态系统。它不用科学上网&#xff01;甚至可以不联网&#xff01;本地就能用&#xff0c;像这样↓&#xff1a; 如何使用&#xff…

Transactional事务失效场景汇总

文章目录 1、前言2、失效场景2.1、Service没有被Spring管理2.2、事务方法被final、static关键字修饰2.3、同一个类中&#xff0c;方法内部调用2.4、方法的访问权限不是public2.5、数据库的存储引擎不支持事务2.6、Transactional 注解配置错误2.7、使用了错误的事务传播机制2.8、…

【校招VIP】浙大、上海交大、北航等顶级985都参加的大厂校招计划 前两年就业率97%

我们除了互联网的业务外&#xff0c;还有一个比较厉害的小业务&#xff0c;叫稳拿计划。 国内有很多985的学生都报考了大厂的就业班稳拿计划&#xff0c;且过去几届的就业率都达到了97%以上。 只有极少数人&#xff0c;没有找到符合要求的工作。 如果学员没有达到我们规定的…

vue3+ts+pinia+vite一次性全搞懂

vue3tspiniavite项目 一&#xff1a;新建一个vue3ts的项目二&#xff1a;安装一些依赖三&#xff1a;pinia介绍、安装、使用介绍pinia页面使用pinia修改pinia中的值 四&#xff1a;typescript的使用类型初识枚举 一&#xff1a;新建一个vue3ts的项目 前提是所处vue环境为vue3&…

统信UOS + Windows双系统安装教程

全文导读&#xff1a;本文主要介绍了AMD架构下&#xff08;Intel/amd/兆芯/海光&#xff09;的机器同时安装Windows系统UOS系统的方法。 准备环境 1、下载好UOS系统镜像&#xff08;AMD64&#xff09;&#xff0c;下载地址&#xff1a;https://www.chinauos.com/resource/down…

代码随想录算法训练营第52天|300.最长递增子序列,674. 最长连续递增序列,718. 最长重复子数组

代码随想录算法训练营第52天|300.最长递增子序列&#xff0c;674. 最长连续递增序列&#xff0c;718. 最长重复子数组 300.最长递增子序列674. 最长连续递增序列718. 最长重复子数组 300.最长递增子序列 题目链接&#xff1a;300.最长递增子序列&#xff0c;难度&#xff1a;中…

C/C++外观模式解析:简化复杂子系统的高效方法

C外观模式揭秘&#xff1a;简化复杂子系统的高效方法 引言设计模式的重要性外观模式简介与应用场景外观模式在现代软件设计中的地位与价值 外观模式基本概念外观模式的定义与核心思想提供简单接口隐藏复杂子系统设计原则与外观模式的关系外观模式实现外观模式的UML图 外观模式的…

【通过Cpython3.9源码看看python的内存回收机制】

一&#xff1a;建立对象引用计数 1. 相关代码 void _Py_NewReference(PyObject *op) {if (_Py_tracemalloc_config.tracing) {_PyTraceMalloc_NewReference(op);} #ifdef Py_REF_DEBUG_Py_RefTotal; #endifPy_SET_REFCNT(op, 1); #ifdef Py_TRACE_REFS_Py_AddToAllObjects(op…

webRtc播放rtsp视频流(vue2、vue3+vite+ts)

一、下载webRtc 开发环境用的win10版本的。 github上直接下载&#xff0c;速度感人。 Releases mpromonet/webrtc-streamer GitHub 提供资源下载&#xff0c;0积分 https://download.csdn.net/download/weiqiang915/87700892 二、启动&#xff0c;测试 webrtc-streame…

辉煌优配|刚刚!“中字头”再度爆发

今天早盘&#xff0c;A股全体持续震动收拾&#xff0c;上证50指数跌破2700点整数关口&#xff0c;沪深300亦失守4100点。 盘面上&#xff0c;国防军工、种业、中字头、电气设备等板块涨幅居前&#xff0c;前期抢手的人工智能、半导体、信创、软件服务等板块全线回调。北上资金净…

高效又稳定的ChatGPT大模型训练技巧总结,让训练事半功倍!

文&#xff5c;python 前言 近期&#xff0c;ChatGPT成为了全网热议的话题。ChatGPT是一种基于大规模语言模型技术&#xff08;LLM&#xff0c; large language model&#xff09;实现的人机对话工具。现在主流的大规模语言模型都采用Transformer网络&#xff0c;通过极大规模的…