9.MyBatis-Plus

news2025/2/26 5:21:24
1、前期准备
a. 创建数据库
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)
);

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');
b. 配置项目环境

配置Java编译器:

项目和文件的编码:

c. 添加依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

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

    <!--mysql依赖-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!--lombok用来简化实体类-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
d. 配置文件
# 配置MySQL
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/syt_mp?serverTimezone=GMT%2B8
    username: root
    password: 0903he0419
  • 这里的 url 使用了 ?serverTimezone=GMT%2B8 后缀,因为8.0版本的jdbc驱动需要添加这个后缀,否则运行测试用例报告如下错误:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more
  • 这里的 driver-class-name 使用了 com.mysql.cj.jdbc.Driver ,在 jdbc 8 中 建议使用这个驱动,否则运行测试用例的时候会有 WARN 信息
e. 启动类
@SpringBootApplication
@MapperScan("com.lemon.demomp.mapper")
public class DemompApplication {

    public static void main(String[] args) {

        SpringApplication.run(DemompApplication.class, args);
    }

}
  • 在启动类添加注解:@MapperScan("com.lemon.demomp.mapper")
f. 添加实体
@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
g. 添加mapper
@Repository
public interface UserMapper extends BaseMapper<User> {

}
  • 为了避免报错,可以在dao 层 的接口上添加 @Repository 注
h. 查看 sql 输出日志
# mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
2、主键策略

插入操作:

//添加
@Test
public void testAdd() {
    User user = new User();
    user.setName("lucy");
    user.setAge(20);
    user.setEmail("1243@qq.com");
    int insert = userMapper.insert(user);
    System.out.println(insert);
}
a. ASSIGN_ID

MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)

@TableId(type = IdType.ASSIGN_ID)
private Long id;
b. AUTO 自增策略

需要在创建数据表的时候设置主键自增

实体字段中配置@TableId(type = IdType.AUTO)

@TableId(type = IdType.AUTO)
private Long id;

要想影响所有实体的配置,可以设置全局主键配置

#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto

3、自动填充

注意:update时生成的sql自动是动态sql:UPDATE user SET age=? WHERE id=?

更新操作:

// 修改
@Test
public void testUpdate() {
    User user = new User();
    user.setId(1722996412305653764L);
    user.setName("朱棣");
    int count = userMapper.updateById(user);
    System.out.println(count);
}

需求描述:项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作

a. 修改数据库

在User表中添加datetime类型的新的字段 create_time、update_time

b. 修改实体类

实体上增加字段并添加自动填充注解:

@TableField(fill = FieldFill.INSERT)
private Date createTime;  //create_time

@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime; //update_time
c. 实现元对象处理接口

src/hander/MyMetaObjectHandler

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    // mp执行添加操作,这个方法执行
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    // mp 执行修改操作,这个方法执行
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}
4、乐观锁

主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新。

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时,set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

乐观锁实现流程:

a. 修改数据库

在user表中新增version字段数据类型为int,给其设定一个默认值(假设为1)

b. 修改实体类

添加 @Version 注解

@Version
private Integer version;
c. 创建配置类

创建包config,创建文件MybatisPlusConfig.java

此时可以删除主类中的 @MapperScan 扫描注解

@Configuration
@MapperScan("com.lemon.demomp.mapper")
public class MpConfig {
    /**
     * 乐观锁插件
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}
d. 测试方法

根据输出结果可以看到,首先经过查询,user的version是1,然后在更改user的name属性,此时version变为2。自此乐观锁已经生效。

@Test
public void testOptimisticLocker() {
    // 1. 根据id进行查询
    User user = userMapper.selectById(1722996412305653768L);
    user.setName("张三");
    int count = userMapper.updateById(user);
    System.out.println(count);
}
5、查询
a. 批量查询

通过多个id进行批量查询

SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id IN ( ? , ? , ? )

==> Parameters: 1(Integer), 2(Integer), 3(Integer)

/*
* 批量查询
* */
@Test
public void testSelectByIds() {
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
    System.out.println(users);
}
b. 简单条件查询

SELECT id,name,age,email,create_time,update_time,version FROM user WHERE name = ? AND age = ?

==> Parameters: Jack(String), 20(Integer)

/*
* 简单条件查询
* */
@Test
public void testSelectByMap() {
    Map<String, Object> columnMap = new HashMap<>();
    columnMap.put("name", "Jack");
    columnMap.put("age", 20);
    List<User> users = userMapper.selectByMap(columnMap);
    System.out.println(users);
}
6、分页查询
a. 添加分页插件

在配置类中注册分页插件:src/config/MpConfig

/**
 * 分页插件
 */
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}
b. 测试selectPage

Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user LIMIT ?,?

==> Parameters: 0(Long), 3(Long)

/*
* 测试selectPage分页
* */
@Test
public void testSelectPage() {
    Page<User> page = new Page<>(1, 3);
    Page<User> userPage = userMapper.selectPage(page, null);
    // 返回对象得到分页所有数据
    long pages = userPage.getPages(); //总页数
    long current = userPage.getCurrent(); //当前页
    List<User> records = userPage.getRecords();//查询数据集合
    long total = userPage.getTotal();//总记录数
    boolean hasNext = userPage.hasNext();//是否有下一页
    boolean hasPrevious = userPage.hasPrevious();//是否有上一页

    System.out.println(pages);
    System.out.println(current);
    System.out.println(records);
    System.out.println(total);
    System.out.println(hasNext);
    System.out.println(hasPrevious);

}
c. 测试selectMapsSelect

Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user LIMIT ?,?

==> Parameters: 0(Long), 5(Long)

/*
* 测试selectMapsPage
* */
@Test
public void testSelectMapsPage() {
    //Page不需要泛型
    Page<Map<String, Object>> page = new Page<>(1, 5);
    Page<Map<String, Object>> pageParam = userMapper.selectMapsPage(page, null);
    List<Map<String, Object>> records = pageParam.getRecords();
    records.forEach(System.out::println);
    System.out.println(pageParam.getCurrent());
    System.out.println(pageParam.getPages());
    System.out.println(pageParam.getSize());
    System.out.println(pageParam.getTotal());
    System.out.println(pageParam.hasNext());
    System.out.println(pageParam.hasPrevious());
}
7、删除
a. 根据id删除记录

Preparing: DELETE FROM user WHERE id=?

==> Parameters: 1(Long)

/*
* 根据id删除记录
* */
@Test
public void testDelById() {
    int isDeleted = userMapper.deleteById(1L);
    System.out.println(isDeleted);
}
b. 批量删除

Preparing: DELETE FROM user WHERE id IN ( ? , ? , ? )

==> Parameters: 2(Integer), 3(Integer), 4(Integer)

/*
* 批量删除
* */
@Test
public void testDelBatchByIds() {
    int isDeleted = userMapper.deleteBatchIds(Arrays.asList(2, 3, 4));
    System.out.println(isDeleted);
}
c. 简单条件删除

Preparing: DELETE FROM user WHERE name = ? AND age = ?

==> Parameters: Billie(String), 24(Integer)

/*
*
* 简单条件删除
* */
@Test
public void testDelByMap() {
    Map<String, Object> map = new HashMap<>();
    map.put("name", "Billie");
    map.put("age", 24);
    int isDeleted = userMapper.deleteByMap(map);
    System.out.println(isDeleted);
}
8、逻辑删除

物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据

逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

逻辑删除的使用场景

  • 可以进行数据恢复
  • 有关联数据,不便删除
a. 修改数据库

添加逻辑删除字段

ALTER TABLE `user` ADD COLUMN deleted BOOLEAN DEFAULT FALSE COMMENT '逻辑删除'
b. 修改实体类

添加deleted 字段,并加上 @TableLogic 注解

@TableLogic
private Integer deleted;
c. 配置文件(可选)

application.properties 加入以下配置,此为默认值,如果你的默认值和mp默认的一样,该配置可无

mybatis-plus:
  global-config:
    db-config:
      id-type: auto
      logic-delete-value: 1
      logic-not-delete-value: 0
d. 测试逻辑删除

Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0

==> Parameters: 6(Long)

测试后发现,数据并没有被删除,deleted字段的值由0变成了1

测试后分析打印的sql语句,是一条update

注意:被删除前,数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作

/*
* 逻辑删除
* */
@Test
public void testLogicDelete() {
    int isDeleted = userMapper.deleteById(6L);
    System.out.println(isDeleted);
}
e. 测试逻辑删除后的查询

MyBatis Plus中查询操作也会自动添加逻辑删除字段的判断

SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0

/*
* 测试逻辑删除后的查询
* */
@Test
public void testLogicDeleteSelect() {
    List<User> users = userMapper.selectList(null);
    users.forEach(System.out::println);
}
9、条件构造器

Wrapper

条件构造抽象类,最顶端父类

AbstractWrapper

用于查询条件封装,生成 sql 的 where 条件

QueryWrapper

查询条件封装

UpdateWrapper

Update 条件封装

AbstractLambdaWrapper

使用Lambda 语法

LambdaQueryWrapper

用于Lambda语法使用的查询Wrapper

LambdaUpdateWrapper

Lambda 更新封装Wrapper

a. ge、gt、le、lt、isNull、isNotNull

UPDATE user SET deleted=1 WHERE deleted=0 AND (name IS NOT NULL AND age >= ? AND email IS NOT NULL)

==> Parameters: 50(Integer)

/*
* ge、gt、le、lt、isNull、isNotNull
* delete
* */
@Test
public void testQuery() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.isNotNull("name")
            .ge("age",50)
            .isNotNull("email");
    int deleted = userMapper.delete(queryWrapper);
    System.out.println("deleted return count= " + deleted);
}
b. eq、ne

SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0 AND (name = ?)

==> Parameters: 张三(String)

注意:seletOne()返回的是一条实体记录,当出现多条时会报错

/*
* eq、ne
* selectOne
* */
@Test
public void testSelectOne() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("name", "张三");
    User user = userMapper.selectOne(queryWrapper);
    System.out.println(user);
}
c. between、notBetween

SELECT COUNT( 1 ) FROM user WHERE deleted=0 AND (age BETWEEN ? AND ?)

==> Parameters: 60(Integer), 80(Integer)

/*
* between,notBetween
* selectCount
* */
@Test
public void testSelectCount() {
    QueryWrapper<User> queryWrapper  = new QueryWrapper<>();
    queryWrapper.between("age", 60, 80);
    Integer count = userMapper.selectCount(queryWrapper);
    System.out.println(count);
}
d. like、notLike、likeLeft、likeRight

SELECT name,age FROM user WHERE deleted=0 AND (name LIKE ? AND email LIKE ?)

==> Parameters: %e%(String), 5%(String)

selectMaps()返回Map集合列表,通常配合select()使用

/*
* like,notLike,likeLeft,likeRight
* selectMaps
* */
@Test
public void testSelectMaps() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.select("name", "age")
            .like("name", "e")
            .likeRight("email", "5");
    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
    maps.forEach(System.out::println);
}
e. orderBy、orderByDesc、orderByAsc

SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0 ORDER BY age DESC,id DESC

/*
* orderBy、orderByDesc、orderByAsc
* selectList
* */
@Test
public void testSelectList() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.orderByDesc("age", "id");
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}
10、查询方式

setSqlSelect

设置 SELECT 查询字段

where

WHERE 语句,拼接 + WHERE 条件

and

AND 语句,拼接 + AND 字段=值

andNew

AND 语句,拼接 + AND (字段=值)

or

OR 语句,拼接 + OR 字段=值

orNew

OR 语句,拼接 + OR (字段=值)

eq

等于=

allEq

基于 map 内容等于=

ne

不等于<>

gt

大于>

ge

大于等于>=

lt

小于<

le

小于等于<=

like

模糊查询 LIKE

notLike

模糊查询 NOT LIKE

in

IN 查询

notIn

NOT IN 查询

isNull

NULL 值查询

isNotNull

IS NOT NULL

groupBy

分组 GROUP BY

having

HAVING 关键词

orderBy

排序 ORDER BY

orderAsc

ASC 排序 ORDER BY

orderDesc

DESC 排序 ORDER BY

exists

EXISTS 条件语句

notExists

NOT EXISTS 条件语句

between

BETWEEN 条件语句

notBetween

NOT BETWEEN 条件语句

addFilter

自由拼接 SQL

last

拼接在最后,例如:last(“LIMIT 1”)

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

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

相关文章

短路语法 [SUCTF 2019]EasySQL1

打开题目 输入字符的时候啥也不回显。只有输入数字的时候页面有回显 但是当我们输入union&#xff0c;from&#xff0c;sleep&#xff0c;where&#xff0c;order等&#xff0c;页面回显nonono&#xff0c;很明显过滤了这些关键词 最开始我的思路是打算尝试双写绕过 1;ununion…

TS-08-A-2D、TS-08-B-1H插装式电磁比例溢流阀放大器

TS-08-A-2D、TS-08-B-1H插装式电磁比例溢流阀放大器持续的电磁铁、高效能的电磁铁结构、可选的线圈电压和终端、工业化通用插孔、紧凑的结构。 螺纹插装式、先导滑阀式减压溢流阀&#xff0c;利用可变电流输入可实现指定范围内的输出压力连续调节。输出压力与 DC 电流输入成比…

[Jenkins] 物理机 安装 Jenkins

这里介绍Linux CentOS系统直接Yum 安装 Jenkins&#xff0c;不同系统之间类似&#xff0c;操作命令差异&#xff0c;如&#xff1a;Ubuntu用apt&#xff1b; 0、安装 Jenkins Jenkins是一个基于Java语言开发的持续构建工具平台&#xff0c;主要用于持续、自动的构建/测试你的软…

Linux学习教程(第三章 Linux文件和目录管理)1

第三章 Linux文件和目录管理&#xff08;初识Linux命令&#xff09; 对初学者来说&#xff0c;管理 Linux 系统中的文件和目录&#xff0c;是学习 Linux 至关重要的一步。 为了方便管理文件和目录&#xff0c;Linux 系统将它们组织成一个以根目录 / 开始的倒置的树状结构。Li…

【架构师】的修炼之道都需要学习哪些?看看这些就够了

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; &#x1f40b; 希望大家多多支…

代码随想录图论|130. 被围绕的区域 417太平洋大西洋水流问题

130. 被围绕的区域 **题目&#xff1a;**给你一个 m x n 的矩阵 board &#xff0c;由若干字符 ‘X’ 和 ‘O’ &#xff0c;找到所有被 ‘X’ 围绕的区域&#xff0c;并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。 题目链接&#xff1a;130. 被围绕的区域 解题思路&#xff1a…

《向量数据库指南》——2023云栖大会现场,向量数据库Milvus Cloud成关注焦点

近期,广受关注的2023 云栖大会正式收官,来自全球各地的开发者集聚一堂,共同探索 AI 时代的更多可能性。 云栖大会是由阿里巴巴集团主办的科技盛宴,是中国最早的开发者创新展示平台。据悉,今年云栖大会的主题为“计算,为了无法计算的价值”,共吸引了全球 44 个国家和地区…

用封面预测书的价格【图像回归】

今天&#xff0c;我将介绍计算机视觉的深度学习应用&#xff0c;用封面简单地估算一本书的价格。 我没有看到很多关于图像回归的文章&#xff0c;所以我为你们写这篇文章。 距离我上一篇文章已经过去很长时间了&#xff0c;我不得不承认&#xff0c;作为一名数据科学家&#x…

OceanBase杨冰:完全自研,才能逢山开路遇水搭桥

11月16日&#xff0c;在OceanBase2023年度发布会上&#xff0c;OceanBase CEO杨冰介绍&#xff0c;中国数字经济的蓬勃发展催生了对分布式数据库的强大需求&#xff0c;这种需求也牵引了OceanBase坚定投入自主研发&#xff0c;从而推动树立了分布式数据库的四项新标准。 据了解…

Harmony SDK API 版本 与 Harmony OS 版本对照表,及如何查看鸿蒙手机Harmony SDK Api 版本

Harmony SDK API 版本 与 Harmony OS 版本对照表 Harmony OSHarmony SDK APIHarmony 4.09Harmony 3.19Harmony 3.08Harmony 3.0 pre7Harmony 2.2.06Harmony 2.1.05Harmony 2.04 具体到真机上可能会有差异&#xff0c;如我的手机OS版本是2.0&#xff0c;按照上面表应该是4&…

jsp中使用PDF.js实现pdf文件的预览

本文介绍的是在使用jsp作为模板引擎的spring-mvc项目中&#xff0c;如何利用 PDF.js实现pdf文件的预览。 1、下载 PDF.js Getting Started (mozilla.github.io) 下载解压后其中有两个目录&#xff0c;直接将这两个文件夹放到项目的web资源目录中。此时相当于把PDF.js这个项目也…

使用Kohya_ss训练Stable Diffusion Lora

Stable Diffusion模型微调方法 Stable Diffusion主要有 4 种方式&#xff1a;Dreambooth, LoRA, Textual Inversion, Hypernetworks。 Textual Inversion &#xff08;也称为 Embedding&#xff09;&#xff0c;它实际上并没有修改原始的 Diffusion 模型&#xff0c; 而是通过…

Android 14 Beta 1

Android 14的第一个 Beta 版&#xff0c;围绕隐私、安全、性能、开发人员生产力和用户定制等核心主题构建&#xff0c;同时继续改进平板电脑、可折叠设备等大屏幕设备的体验。我们一直在完善 Android 14 的功能和稳定性方面取得稳步进展&#xff0c;现在是时候向开发者和早期采…

软件系统集成指南

软件产品集成是将各种软件组件、模块和代码组装成最终可执行、可应用的软件产品的过程。这个过程涉及到将工作产品转化为产品的组装过程。在软件工程中&#xff0c;产品集成是一个重要的环节&#xff0c;通过持续性集成&#xff0c;将产品集成的过程常态化、自动化。做好产品集…

收集整理微信小程序源码精选8500套(不同行业的源码集合)/带后台+含搭建开发教程

这下面分享的是精心收集整理的微信小程序源码精选8500套&#xff0c;它含有不同行业的源码集合&#xff0c;带后台&#xff0c;而且含搭建开发教程。可以转存起来&#xff0c;需要的时候直接搜索关键词查找就行了&#xff0c;方便得很。 很多伙伴学习小程序不知怎么开始&#…

【Vue-Demo】倒计时3秒后返回首页

首页path:/ 倒计时结束后要清除计时器&#xff0c;防止内存泄漏&#xff1a; if (this.count 0) {clearInterval(this.timer); }<!-- ErrorJump.vue --> <template><h2>Error&#xff1a;找不到页面&#xff01;</h2><h4>{{ count }}S后<R…

01序列 卡特兰数

解法&#xff1a; 将01序列置于坐标轴上&#xff0c;起始点为原点。0表示向右走&#xff0c;1表示向上走。这样就可以将前缀0的个数不少于1的个数就可以转换为路径上的点&#xff0c;横坐标大于纵坐标&#xff0c;也就是求合法路径个数。 注意题目mod的数是质数&#xff0c;所…

【嵌入式项目应用】__单片机STM32有什么好的裸机程序架构思路推荐?

目录 前言 没设计好程序架构&#xff0c;根本做不稳定。 按照我的思维&#xff0c;我会这样去设计程序&#xff1a; 那这样的好处是什么&#xff1f; (*&#xffe3;︶&#xffe3;)创作不易&#xff01;期待你们的 点赞、收藏和评论喔。 前言 在我刚出来的时候&#x…

Android笔记(十三):结合JetPack Compose和CameraX实现视频的录制和存储

在“Android笔记&#xff08;八&#xff09;&#xff1a;基于CameraX库结合Compose和传统视图组件PreviewView实现照相机画面预览和照相功能”&#xff0c;文中介绍了拍照功能的实现&#xff0c;在本文中将介绍结合JetPack Compose和CameraX实现视频的录制。 新建一个项目 在项…

nn.Embedding()的原理

nn.Embedding()的原理&#xff1a; 定义一个Embedding&#xff1a; embeddings nn.Embedding(num_embeddings10, embedding_dim3)vocab_size : 10 输出维度为&#xff1a; 3 假定输入inputs如下&#xff1a; inputs torch.tensor([[1,3,6, 8],[9,1,3,5] ],dtypetorch.lo…