MyBatis-Plus知识总结

news2024/11/16 1:02:04

1. MP前瞻


官网:https://baomidou.com/

1、MyBatis-Plus是什么:MyBatis-Plus(简称MP)是一个MyBatis的增强工具,它在MyBatis的基础上只做增强不做改变,为简化开发、提供效率而生。并且MP内部提供了丰富的 API,可以解放单表CRUD方法的编写,使开发者更专注于业务逻辑的实现。

image-20240728055756064

2、MP的特性:无侵入损耗小,提供强大的CRUD操作,支持Lambda形式调用,支持 ActiveRecord 形式调用,支持主键生成,内置分页插件、代码生成器和性能分析插件等等。

3、支持的数据库:有MySQL、PostgreSQL、MariaDB、Oracle、OceanBase、SQLite、SQLServer、H2、DB2、达梦、人大金仓、虚谷等等。

4、SpringBoot整合MP,需要引入的依赖:

<!--SpringBoot2-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.5</version>
</dependency>
<!--SpringBoot3-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    <version>3.5.5</version>
</dependency>

image-20240728180619627


2. MP快速入门


1、执行sql脚本:

CREATE DATABASE `mp_db` CHARACTER SET utf8mb4;

use `mp_db`;

CREATE TABLE `user`
(
    `id` BIGINT NOT NULL COMMENT '主键ID',
    `name` VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
    `age` INT 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, 'JackMa', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

2、创建SpringBoot工程

3、引入mp相关的依赖坐标:

<dependencies>
  <!--mp-->
  <dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.5</version>
  </dependency>
    <!--mysql驱动-->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>
    <!--lombok简化实体开发-->
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
  </dependency>
  <!--单元测试起步依赖-->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
  </dependency>
</dependencies>

4、在 application.yml中,配置数据库的连接信息:

#DataSource Config
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mp_db?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456


#MybatisPlus Config
mybatis-plus:
  configuration:
    #开启SQL日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

5、编写实体类:

package cn.aopmin.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 用户实体
 *
 * @author 白豆五
 * @since 2024/7/28
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")//指定要绑定的表名
public class User implements Serializable {
    @TableId(type = IdType.AUTO, value = "id")// 设置主键生成策略
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

实体类与表名规则要求:

  • MP默认情况下,要求:实体类和表名 要符合 下划线与驼峰的映射规则;
  • 如果不符合:就需要在实体类上加@TableName("表名")

实体类里属性与字段的规则要求:

  • 默认情况下,要求每个属性都必须有一个对应的字段,属性名和字段名要符合 驼峰与下划线映射规则;

  • 非主键字段:

    • 如果一个属性名,和字段名不对应,怎么办?加@TableField(value="字段名")
    • 如果一个属性,没有对应的字段存在,怎么办?加@TableField(exists=false)
    • 如果一个属性,不想查询对应字段的值,怎么办?加@TableField(select=false)
  • 主键字段:

    • 要使用@TableId(value=“字段名”, type=主键生成策略)
    • 主键生成策略,设置的方式:实体类里主键属性上加 @TableId(type=IdType.策略名)
      • NONE:不设置,跟随全局
      • AUTO:主键值自增,前提是原有的数据库主键支持自增
      • INPUT:由我们的代码设置主键值,不让MP生成主键值
      • ASSIGN_ID:雪花算法。根据时间戳+机器码+序列号生成最终的Long类型的数字,特点是单调递增的
      • ASSIGN_UUID:UUID算法。不推荐,因为UUID值是乱序的,会影响主键字段上的索引

6、编写mapper接口:

package cn.aopmin.mapper;

import cn.aopmin.domain.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * 定义一个Mapper接口,继承BaseMapper<实体类> 
 *
 * @author 白豆五
 * @since 2024/7/28
 */
public interface UserMapper extends BaseMapper<User> {
}

7、在启动类上加上@MapperScan注解:

package cn.aopmin;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan("cn.aopmin.mapper") // 扫描mapper接口
@SpringBootApplication
public class MPApplication {
    public static void main(String[] args) {
        SpringApplication.run(MPApplication.class, args);
    }
}

8、测试:

package cn.aopmin;

import cn.aopmin.domain.User;
import cn.aopmin.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

/**
 * mp快速入门
 *
 * @author 白豆五
 * @since 2024/7/28
 */
@SpringBootTest
public class Demo01MpTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void test() {
        List<User> list = userMapper.selectList(null);
        list.forEach(System.out::println);
    }

}

image-20240728174849025


3. mapper内置方法


文档地址:https://baomidou.com/guides/data-interface/#mapper-interface

MP内置了强大的BaseMapper,它已经提供好了单表CURD功能:只要我们的Mapper接口继承了BaseMapper,然后泛型设置表名对应的实体类,就可以直接使用整套的单表CURD功能了。

Mapper接口常用方法:

  • 新增:int insert(T entity)
  • 根据id修改:int updateById(T entity)
  • 根据id删除:int deleteById(Serializable id)
  • 根据id查询:T selectById(Serializable id)
  • (根据条件) 查询一条:T selectOne(Wrapper<T> w)
  • (根据条件) 查询列表:List<T> selectList(Wrapper<T> w)
  • (根据条件) 查询数量: Integer selectCount(Wrapper<T> w)
  • (根据条件) 分页查询: IPage selectPage(IPage page, Wrapper<T> w)

4. service内置方法


文档地址:https://baomidou.com/guides/data-interface/#service-interface

同时MP也提供了通用Service接口,如果Service层也想操作,只需继承IService 接口就可以得到整套单表CURD功能。

Service接口常用方法:

  • 新增:boolean save(T entity)
  • 根据id修改:boolean updateById(T entity)
  • 根据id删除:boolean removeById(Serializable id)
  • 根据id查询:getById(Serializable id)
  • (根据条件) 查询一条:T getOne(Wrapper<T> queryWrapper)
  • (根据条件) 查询列表:List<T> list(Wrapper<T> queryWrapper)
  • (根据条件) 查询数量: int count(Wrapper<T> w)
  • (根据条件) 分页查询: IPage page(IPage page, Wrapper<T> w)

5.wrapper条件构造器


文档地址:https://baomidou.com/guides/wrapper/

MyBatis-Plus 的 Wrapper 类是构建查询和更新条件的核心工具,它允许开发者以链式编程方式构造where条件,从而简化SQL语句的编写、降低SQL注入的风险。

Wrapper 常用子类:

  • QueryWrapper、UpdateWrapper:使用时容易写错,但使用更灵活。
  • LambdaQueryWrapper、LambdaUpdateWrapper:没有QueryWrapper、UpdateWrapper灵活,但是不易写错(拼接条件不用指定表字段,而是对应属性名),使用的更多一些。

image-20240728190926812

QueryWrapper的用法:

//直接new的方式。
QueryWrapper<实体类> wrapper = new QueryWrapper<实体类>()
    .select("字段1,字段2,字段3 as 别名, ifnull(...) as xx")
    //条件方法:eq, ne, gt, ge, lt, le, like, notLike, in, notIn, isNull, isNotNull....
    .条件方法(字段名,) 
    .条件方法(是否要拼接此条件, 字段名,)
    .orderByAsc("字段名...").orderByDesc("字段名...")
    
//直接Wrappers的静态方法方式。
QueryWrapper<实体类> wrapper = Wrappers.<实体类>query()
    .select("字段1,字段2,字段3 as 别名, ifnull(...) as xx")
    //条件方法:eq, ne, gt, ge, lt, le, like, notLike, in, notIn, isNull, isNotNull....
    .条件方法(字段名,) 
    .条件方法(是否要拼接此条件, 字段名,)
    .orderByAsc("字段名...").orderByDesc("字段名...")    
    
List list = xxxMapper.selectList(wrapper);
  • 条件方法:
    • eq(“字段名”, 值): 等于。
    • ne(“字段名”, 值):不等于。
    • gt(“字段名”, 值): 大于。
    • ge(“字段名”, 值): 大于等于。
    • lt(“字段名”, 值): 小于。
    • le(“字段名”, 值): 小于等于。
    • like(“字段名”, 值): 模糊匹配,使用 % 作为通配符。
    • notLike(“字段名”, 值): 不模糊匹配,使用 % 作为通配符。
    • in(“字段名”, 值列表): 在某个集合中。
    • notIn(“字段名”, 值列表): 不在某个集合中。
    • isNull(“字段名”): 为空。
    • isNotNull(“字段名”): 不为空。
    • orderByAsc(“字段名”): 按字段名升序排序。
    • orderByDesc(“字段名”): 按字段名降序排序。

LambdaQueryWrapper的用法:

//直接new
LambdaQueryWrapper<实体类> wrapper = new LambdaQueryWrapper<实体类>()
    .select(实体类::get属性, ....)
    .条件方法(实体类::get属性,)
    .条件方法(是否要拼接此条件, 实体类::get属性,)
    .orderByAsc(实体类::get属性,..).orderByDesc(实体类::get属性,...)

//使用Wrappers的静态方法
LambdaQueryWrapper<实体类> wrapper = Wrappers.<实体类>lambdaQuery()
    .select(实体类::get属性, ....)
    .条件方法(实体类::get属性,)
    .条件方法(是否要拼接此条件, 实体类::get属性,)
    .orderByAsc(实体类::get属性,..).orderByDesc(实体类::get属性,...)

UpdateWrapper的用法:

// 直接new的方式。  
UpdateWrapper<实体类> wrapper = new UpdateWrapper<实体类>()  
    // 设置更新字段  
    .set("字段名",)   
    // 设置更新条件,使用与QueryWrapper相同的条件方法  
    .条件方法("字段名",)int result = userMapper.update(entity, wrapper);  
    

// 使用Wrappers的静态方法 
UpdateWrapper<实体类> wrapper = Wrappers.<实体类>update()  
    // 设置更新字段  
    .set("字段名",)   
    // 设置更新条件,使用与QueryWrapper相同的条件方法  
    .条件方法("字段名",)// 执行更新操作  
int result = xxxMapper.update(entity, wrapper);

LambdaUpdateWrapper的用法:

// 直接new的方式。  
LambdaUpdateWrapper<实体类> wrapper = new LambdaUpdateWrapper<实体类>()  
    // 设置更新字段  
    .set("字段名",)   
    // 设置更新条件
    .条件方法("字段名",)int result = userMapper.update(entity, wrapper);  


// 使用Wrappers的静态方法 
LambdaUpdateWrapper<实体类> wrapper = Wrappers.<实体类>lambdaUpdate()  
    // 设置更新字段  
    .set("字段名",)   
    // 设置更新条件
    .条件方法("字段名",)// 执行更新操作  
int result = userMapper.update(entity, wrapper);   

6. MP分页查询


文档地址:https://baomidou.com/plugins/pagination/

MyBatis-Plus 的分页插件 PaginationInnerInterceptor 提供了强大的分页功能,支持多种数据库,使得分页查询变得简单高效。

使用步骤:

1、在配置类或启动类中配置 分页插件

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//如果配置多个插件,切记分页最后添加
    return interceptor;
}

2、调用mapper接口的selectPage方法进行分页查询

Page<实体类> page = xxxMapper.selectPage( new Page(页码,每页几条), wrapper对象 );

page.getTotal();  //获取总数量
page.getPages();  //获取总页数
page.getRecords();//获取数据列表

分页API介绍:

MP的Mapper接口提供的分页查询方法是:IPage selectPage(IPage page, Wrapper wrapper)

  • 参数page:用于封装分页条件,包括页码和查询数量

  • 参数wrapper:用于封装查询条件,实现条件查询并分页

  • 返回值Page:分页查询的结果

IPage:是一个接口;Page是它的实现类,表示分页信息对象。

  • 在执行分页查询前,把分页参数封装成Page对象
  • 当执行分页查询后,MP会把查询结果封装到这个Page对象中。

Page对象常用方法:

  • new Page(pageNumber, pageSize):创建分页信息Page对象
  • getCurrent():获取当前页码
  • getPages():获取总页数
  • getSize():获取每页几条
  • getTotal():获取总数量

示例:

/ 创建分页对象,当前页为1,每页显示10条记录  
IPage<User> page = new Page<>(1, 10);  

// 创建查询条件  
QueryWrapper<User> wrapper = new QueryWrapper<>();  
wrapper.eq("status", 1); // 查询条件:状态为1  

// 执行分页查询  
IPage<User> resultPage = userMapper.selectPage(page, wrapper);  

// 获取分页信息  
List<User> userList = resultPage.getRecords(); // 当前页的记录  
long total = resultPage.getTotal(); // 总记录数  
long pages = resultPage.getPages(); // 总页数  

7. 自定义SQL


mp本身是兼容mybatis的,当mp无法满足特定需求时(比如 多表操作),我们也可以像mybatis一样,通过注解或 xml方式手写sql进行扩展。

参考:https://cloud.tencent.com/developer/article/1531517


8. 逻辑删除


在开发中,删除一条数据通常有两种方案可以实现:

  • 物理删除:直接从数据库中删数据。
  • 逻辑删除:并不是真正的删除数据,而是把数据的状态字段值设置为“已删除”状态;当查询数据时,不查询“已删除”状态的数据。

如何实现逻辑删除?

  1. 修改表,增加一个状态字段,用于存储数据是否删除的状态
use mp_db;
alter table user add deleted int default 0;
  1. 修改实体类,增加对应的属性,并给属性上加@TableLogic
@Data
@TableName("user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String userName;
    private String password;
    private Integer age;
    private String tel;
    private String sex;
    //增加@TableLogic注解,这个字段被声明为 逻辑删除状态字段
    @TableLogic
    private int deleted;
}
  1. 修改配置文件,告诉MP,状态字段值为几的时候是已删除,状态是几的时候是未删除
mybatis-plus:
  global-config:
    db-config:
      #logic-delete-field: deleted #全局的默认逻辑删除字段名,即 状态字段名。
      logic-delete-value: 1 #已删除状态的值
      logic-not-delete-value: 0 #未删除状态的值

9. 自动填充字段


文档地址:https://baomidou.com/guides/auto-fill-field/

MP提供了一个便捷的自动填充功能,用于在新增或修改数据时自动填充指定字段,比如 创建时间、更新时间、创建人和修改人等。


10. 多数据源


文档地址:https://baomidou.com/guides/dynamic-datasource/

随着项目规模的扩大和业务需求的复杂化,单一数据源已经不能满足实际开发中的需求。在许多情况下,我们需要同时操作多个数据库,或者需要将不同类型的数据存储在不同的数据库中。这时,多数据源场景成为必不可少的解决方案。

市面上常见的多数据源实现方案如下:

方案1:基于Spring框架提供的AbstractRoutingDataSource
- 优点:简单易用,支持动态切换数据源,适用于少量数据源情况。
- 场景:适用于需要动态切换数据源,且数据库较少的情况。
- 文档地址:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jdbc/datasource/utils/AbstractRoutingDataSource.html


方案2:使用MP提供的Dynamic-datasource多数据源框架
- 优点:提供了简单的API,支持动态切换和明确定义数据源。
- 文档地址:https://baomidou.com/guides/dynamic-datasource/#dynamic-datasource

 方案3:通过自定义注解在方法或类上指定数据源
- 优点:灵活性高,能够精确地控制数据源切换;在代码中直观明了。
- 场景:适用于需要在代码层面进行数据源切换,并对数据源切换有精细要求的情况。

 方案4:使用动态代理技术,在运行时动态切换数据源,实现多数据源的切换。
- 优点:灵活性高,支持在运行时动态切换数据源;适合对数据源切换的逻辑有特殊需求的情况。
- 场景:适用于需要在运行时动态决定数据源切换策略的情况。

👉传送门


11. 乐观锁


文档地址:https://baomidou.com/plugins/optimistic-locker/

悲观锁:

  • 在自己操作资源数据期间,认为总有其它线程来干扰,所以要添加排他性的、独占性的锁。

    在我加锁操作期间,其它所有线程都要阻塞排队。直到我释放锁,其他线程才可以再抢锁操作。

  • 特点:

    • 安全性高,因为把多线程并发变成了串行
    • 性能较低,因为同一时间只有一个线程能操作,其它线程都是阻塞排队状态
  • 适合:写多读少的情况

  • 技术:synchronized、Lock对象…

乐观锁:

  • 在自己操作资源数据期间,其它线程很少来干扰,所以并不需要真正添加锁,可以有更好的性能

    自己在每次操作数据时,都先校验感知一下,数据是否被其它线程修改过了;如果被其它线程修改过了,就放弃操作或者报错;如果没有被其它线程修改,就直接执行操作。

  • 特点:

    • 安全性足够
    • 性能比较好。因为没有真正加锁,在当前线程操作期间,可以有其它线程执行读操作,不会有任何影响
  • 适合:读多写少的情况

  • 具体实现:

    • CAS思想:Compare And Swap 对比并交换设置。比如:Java里的AtomicInteger底层使用了CAS思想,并不需要真正加锁,也能实现多线程操作时的线程安全性。
    • 版本号:给数据设置版本号,每次变动数据时都要把版本号+1。修改数据就可以感知,数据是否被其它线程修改了

MP的乐观锁,采用的是版本号方式,使用步骤如下:

  1. 给表里增加一个版本号字段
use mp_db;
alter table user add version int default 0;
  1. 给实体类里增加对应的属性,并添加@Version
@Data
@TableName("user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String userName;
    private String password;
    private Integer age;
    private String tel;
    private String sex;
    @TableLogic
    private int deleted;
    
    //增加对应的属性,并添加@Version注解
    @Version
    private int version;  
}
  1. 给配置类或引导类里,配置 乐观锁插件
@Configuration
public class MpConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        //创建拦截器对象MybatisPlusInterceptor
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        
        //添加分页插件PaginationInnerInterceptor,注意数据库的类型。如果数据库是MySQL,就设置DbType.MYSQL
        //interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        
        
        //添加乐观锁插件OptimisticLockerInnerInterceptor
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

12. MP其他功能


  • 代码生成器
  • 动态表名插件
  • SQL分析和打印
  • 防全表更新和删除插件

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

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

相关文章

(已解决,附RDM工具解决方案)如何实现多个redis连接间指定key(键)的数据同步

目录 问题现象&#xff1a; 问题分析&#xff1a; 方法一-重复执行操作&#xff1a; 方法二-redis命令实现导出再导入&#xff1a; 方法三-使用rdb文件实现数据迁移 方法四-RDM工具自带的数据复制功能 总结&#xff1a; 解决方法&#xff1a; 方法一-重复执行…

SpringMVC(包括Servlet,会话技术)理解

目录 前言&#xff1a; Servlet&#xff1a; http请求的内容&#xff1a; 会话技术&#xff1a; Cookie&#xff1a; Session&#xff1a; 案例实现代码&#xff1a; 小总结&#xff08;感想&#xff09;&#xff1a; SpringMVC介绍&#xff1a; 调用流程&#xff1a…

最后一个单词的长度-string

58. 最后一个单词的长度 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int lengthOfLastWord(string s) {int right s.size()-1;while(s[right] ){right--;}int cnt 0;while(right > 0 && s[right] ! ){right--;cnt;}return cnt;} }; 注意…

达梦数据库系列—39.统计信息详解

目录 达梦统计信息 举例 统计信息的缺点 统计信息管理 手动收集 自动收集 查看统计信息 更新统计信息 删除统计信息 达梦统计信息 达梦数据库的统计信息分为表统计信息&#xff0c;列统计信息&#xff0c;索引统计信息。 表&#xff1a;计算表的行数、所占的页数目、…

二百五十、Linux——visudo 命令编辑 /etc/sudoers 文件时报错 “/etc/sudoers 忙,请稍后重试”

一、目的 在Linux上用visudo 命令编辑 /etc/sudoers 文件时报错&#xff0c;/etc/sudoers 忙&#xff0c;请稍后重试 [roothurys23 ~]# sudo visudo visudo: /etc/sudoers 忙&#xff0c;请稍后重试 二、原因分析 1 另一个 visudo 实例正在运行 如果另一个用户或同一个用户…

Mirror学习笔记(一) 简介

文章目录 一、常规学习&#xff1a;Mirror核心功能有服务器和主机 二、时间戳批处理时间戳 三、TCP和UDP四、CCU(同时在线人数)五、SyncDirection(同步方向)六、RTT&#xff08;往返时间&#xff09;七、Connection Quality&#xff08;连接质量&#xff09;八、Lag Compensati…

django档案馆集中管理系统-计算机毕业设计源码31775

目录 摘要 Abstract 第一章 绪论 1.1 选题背景及意义 1.2 国内外研究现状 1.3 研究方法 第二章 相关技术介绍 2.1 MySQL简介 2.2 Python 2.3 Django框架 2.4 Pycharm简介 第三章 档案馆集中管理系统系统分析 3.1 系统可行性分析 3.1.1 技术可行性 3.1.2 经济可行…

FFmpeg研究

1.FFmpeg介绍 FFmpeg的全称是“Fast Forward Moving Picture Expert Group”&#xff0c;组件由命令行应用程序和函数库两部分组成。通俗概括来说&#xff0c;FFmpeg 是一个免费的开源程序库&#xff0c;一个多媒体音视频处理分析工具软件&#xff0c;且提供命令行方式调用&am…

Linux(1)--VMware的安装与配置

Linux Linux是一种自由和开放源码的类Unix操作系统&#xff0c;由林纳斯托瓦兹&#xff08;Linus Torvalds&#xff09;于1991年首次发布。Linux以其高效性、灵活性和稳定性而闻名&#xff0c;广泛应用于各种计算机硬件设备中&#xff0c;包括手机、平板电脑、路由器、视频游戏…

【Win10】记一次蓝屏修复

最近电脑蓝屏了好多次&#xff0c;错误代码为&#xff1a;IRQL_NOT_LESS_OR_EQUAL 直接搜这个错误代码不太好找原因&#xff0c;于是按照这篇文章[1]来打开错误日志文件。 需要先在windows的应用商店中下载WinDbg 然后&#xff0c;打开目录 C:\Windows\Minidump &#xff0c;…

React 学习——组件内通信(兄弟之间)

A组件 > B组件 核心思路&#xff1a; 1、A组件先通过子传父的方式把数据传给父组件App 2、App拿到数据后通过父传子的方式再传递给B组件 import { useState } from "react" function A({onGetMsg}){const AMsg 我是A组件的消息return (<div><button…

如何实现全国产业园数量扩展,小编带你共同探讨树莓集团产业园运营模式

在当前快速发展的经济环境中&#xff0c;产业园区作为促进经济发展和技术创新的重要平台&#xff0c;扮演着越来越重要的角色。通过精心策划的战略布局与科学严谨的发展规划&#xff0c;树莓集团依托持续的创新驱动与科技引领&#xff0c;成功实现了全国产业园数量的显著扩展与…

【HTML入门】第二十课 - 【实战】做一个侧边栏菜单

这一小节&#xff0c;我们还是继续练习纯HTML标签的内容&#xff0c;多练一些&#xff0c;把HTML标签练熟。这就像练武功前的扎马步和一些基本功&#xff0c;功底越深&#xff0c;后边才能练更高深的武功。 这一小节&#xff0c;我们用纯HTML标签做一个侧边栏菜单的功能。就像这…

仿写讯飞AI生成PPT大纲组件

效果 别的不说先上效果 难点 树的实现 &#xff1a;需要递归自身&#xff0c;有丶难度。但是对于各位应该是有手就彳亍。双亲节点样式 &#xff1a;可以观察到双亲节点在连接线左侧是有内容的&#xff0c;叶子节点则没有。连接线&#xff1a;可以观察到双亲节点是实心圆点&a…

华为交换机Telnet配置

华为交换机Telnet配置 一、Telnet概述与作用 1、Telnet简介 Telnet&#xff08;Telnet协议&#xff09;是一种用于远程登录到计算机或网络设备的协议。它允许用户在本地计算机上通过网络连接到远程计算机或设备&#xff0c;并在远程计算机上执行命令和操作。Telnet协议最初是…

SpringCloudAliababa中使用最新版的Seata实现分布式事务

SpringCloud中使用Seata实现分布式事务 Hello&#xff0c;兄弟们好&#xff0c;我是Feri&#xff0c;最近整理了最新的基于Seata-Server2.0实现分布式事务的demo&#xff0c;希望对你有所帮助&#xff0c;有任何问题&#xff0c;可以随时沟通交流&#xff0c;在成为技术大牛的路…

如何处理selenium Webdriver中的文本框?

文本框或字段在整个网页中广泛使用,本文将介绍如何在Java中使用Selenium Webdriver处理文本框。可以有各种文本字段,我们将尝试包括其中的大多数,并执行各种操作,如清除和输入文本。 我们将使用我们的Selenium游乐场网站- testkru,与各种文本框进行交互。您也可以使用同一…

昇思25天学习打卡营第27天|munger85

Vision Transformer图像分类 Vit是最新的用了transformer架构的图像模型&#xff0c;在很多比赛都获得了大奖&#xff0c;是非常优秀的架构。而且据说cnn其实只是vit的一个子集&#xff0c;cnn的卷积其实就是vit在很小的范围做了注意力机制。非常有意思 整个架构就好像这样 图…

七天打造一套量化交易系统:Day6-人工智能在量化投资中的应用

七天打造一套量化交易系统&#xff1a;Day6-人工智能在量化投资中的应用 步骤一&#xff1a;数据获取步骤二&#xff1a;对股票样本进行初步处理步骤三&#xff1a;遗传算法选股遗传算 kmeans 类的主要代码 步骤四&#xff1a;回测结果 遗传算法是一种基础的人工智能算法&#…

springboot惠农服务平台-计算机毕业设计源码50601

目录 1 绪论 1.1 研究背景 1.2研究意义 1.3论文结构与章节安排 2 惠农服务平台app 系统分析 2.1 可行性分析 2.2 系统功能分析 2.3 系统用例分析 2.4 系统流程分析 2.5本章小结 3 惠农服务平台app 总体设计 3.1 系统功能模块设计 3.2 数据库设计 表access_token (…