MyBatis-Plus学习总结

一.快速入门

(一)简介

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

(二)快速入门

1.准备数据库脚本
2.准备boot工程
(1)创建空项目
(2)创建maven模块
3.导入依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.0.5</version></parent><groupId>com.yan</groupId><artifactId>mybatis-plus-base-quick-01</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><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></dependency><!-- mybatis-plus  --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version></dependency><!-- 数据库相关配置启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><!-- druid启动器的依赖  --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.18</version></dependency><!-- 驱动类--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.28</version></dependency></dependencies><!--    SpringBoot应用打包插件--><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
4.配置文件和启动类

完善连接池配置:

通过源码分析,druid-spring-boot-3-starter目前最新版本是1.2.18,虽然适配了SpringBoot3,但缺少自动装配的配置文件,需要手动在resources目录下创建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,文件内容如下!

com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure

连接池配置

resources/application.yml

# 连接池配置
spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedruid:url: jdbc:mysql:///day01username: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver

启动类

@MapperScan("com.xx.mapper")
@SpringBootApplication
public class MainApplication {public static void main(String[] args) {SpringApplication.run(MainApplication.class,args);}}
5.编写实体类和Mapper接口 
@Data
public class User {private Long id;private String name;private Integer age;private String email;
}

继承mybatis-plus提供的基础Mapper接口,自带crud方法!

public interface UserMapper extends BaseMapper<User> {//定义方法}
6.编写测试类
@SpringBootTest
public class SpringBootMybatisPlusTest {@Autowiredprivate UserMapper userMapper;@Testpublic void test() {List<User> list = userMapper.selectList(null);System.out.println("users:" + list);}}

二.核心功能

(一)基于Mapper接口的crud

通用 CRUD 封装BaseMapper接口,Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器! 内部包含常见的单表操作!

Insert方法

// 插入一条记录
// T 就是要插入的实体对象
// 默认主键生成策略为雪花算法(后面讲解)
int insert(T entity);

Delete方法

// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);// 根据 ID 删除
int deleteById(Serializable id);// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

Update方法

// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);// 根据 ID 修改  主键属性必须值
int updateById(@Param(Constants.ENTITY) T entity);

实体类属性值为Null则不会修改,所以,实体类的属性必须是包装类型,如果不是,例如int类型,会赋初值为0,会将数据库的年龄修改为0

whereWrapper为null,表示全部修改

Select方法

// 根据 ID 查询
T selectById(Serializable id);// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

 (二)自定义和多表映射

mybatis-plus: # mybatis-plus的配置# 默认位置 private String[] mapperLocations = new String[]{"classpath*:/mapper/**/*.xml"};    mapper-locations: classpath:/mapper/*.xml
public interface UserMapper extends BaseMapper<User> {//正常自定义方法!//可以使用注解@Select或者mapper.xml实现List<User> queryAll();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace = 接口的全限定符 -->
<mapper namespace="com.xxx.mapper.UserMapper"><select id="queryAll" resultType="user" >select * from user</select>
</mapper>

 (三)基于Service接口CRUD

1.接口继承IServce接口
public interface UserService extends IService<User> {
}
 2.类继承ServiceImpl实现类
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService{}
3.测试
@SpringBootTest
public class SpringBootMybatisPlusTest {@Autowiredprivate UserService userService;@Testpublic void test_save() {ArrayList<User> lists = new ArrayList<>();User user = new User(null, "张三三", 32, "22445432@qq.com");User user2 = new User(null, "李四四", 32, "3423423@qq.com");lists.add(user);lists.add(user2);userService.saveBatch(lists);}@Testpublic void test_saveOrUpdate() {User user = new User(null, "王五", 23, "234234@qq.com");//id有值则为修改,否则为更新boolean b = userService.saveOrUpdate(user);}@Testpublic void test_getOrList() {User byId = userService.getById(1);//返回单个对象List<User> list = userService.list(null);//查询全部}
}

 (四)分页查询实现

1.导入分页插件

@SpringBootApplication
@MapperScan("com.yan.mapper")
public class Main {public static void main(String[] args) {SpringApplication.run(Main.class, args);}@Beanpublic MybatisPlusInterceptor plusInterceptor() {//mybaits-plus的插件集合[加入到这个集合中即可,分页插件.....]MybatisPlusInterceptor mybatisPlusInterceptor= new MybatisPlusInterceptor();//分页插件mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());return mybatisPlusInterceptor;}
}
2.非自定义的mapper方法使用分页

@SpringBootTest
public class SpringBootMybatisPlusTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testPage(){Page<User> page = new Page<>(1,3);userMapper.selectPage(page,null);//结果 page最后也会被封装结果long current = page.getCurrent();long size = page.getSize();List<User> records = page.getRecords();long total = page.getTotal();}}
 3.自定义的mapper方法使用分页
(1)定义接口

传入参数携带Ipage接口

返回结果为IPage

public interface UserMapper extends BaseMapper<User> {//定义一个根据年龄参数查询,并且分页的方法IPage<User> queryByAge(IPage<User> page,@Param("age") Integer age);
}
 (2)接口实现
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yan.mapper.UserMapper">
<select id="queryByAge" resultType="com.yan.pojo.User">select *from userwhere age > #{age}
</select></mapper>
(3)测试
  @Testpublic void testPage2(){Page<User> page = new Page<>(1,3);IPage<User> userIPage = userMapper.queryByAge(page, 4);}

 (五)条件构造器的使用

1.基于QueryWrapper组装条件
(1)案例

 查询用户名包含a,年龄在20--30之间,邮箱不为Null的,按年龄降序查询用户,如果年龄相同则按id升序排列

  @Testpublic void test_01() {//查询用户名包含a,年龄在20--30之间,邮箱不为Null的,按年龄降序查询用户,如果年龄相同则按id升序排列QueryWrapper<User> queryWrapper= new QueryWrapper<>();queryWrapper.like("name", "a").between("age", 20, 30).isNotNull("email").orderByDesc("age").orderByAsc("id");userMapper.selectList(queryWrapper);}

删除email为空的用户 

   @Testpublic void test2() {//删除邮箱为空的QueryWrapper<User> queryWrapper= new QueryWrapper<>();queryWrapper.isNull("email");int delete = userMapper.delete(queryWrapper);}

将年龄大于20并且用户名中包含有a或邮箱为null的用户信息修改

    @Testpublic void test3() {QueryWrapper<User> queryWrapper= new QueryWrapper<>();queryWrapper.gt("age", 20).like("name", "a").or().isNull("email");User user = new User(null, "test", 88, "fdfsdf");userMapper.update(user, queryWrapper);}
(2)组装条件 
(3)指定列映射

要给User对象设置无参构造器!

 @Testpublic void test4() {QueryWrapper<User> queryWrapper= new QueryWrapper<>();queryWrapper.gt("id", 1).select("name", "age");List<User> users = userMapper.selectList(queryWrapper);System.out.println(users);}
 (4)condition判断组织条件
public Children eq(boolean condition, R column, Object val) {return this.addCondition(condition, column, SqlKeyword.EQ, val);
}
 @Testpublic void test6() {//前端传入两个参数//name不为空,作为条件查询//age>18 作为条件,查询=String name = "";Integer age = 19;QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();objectQueryWrapper.eq(StringUtils.isNotBlank(name), "name",name).eq(age != null && age > 18, "age", age);userMapper.selectList(objectQueryWrapper);}
2.UpdateWrapper组装条件

使用updateWrapper可以随意设置列的值!! 

使用queryWrapper + 实体类形式可以实现修改,但是无法将列值修改为null值!

将年龄大于20并且用户名中包含有a或邮箱为null的用户信息修改

@SpringBootTest
public class MybatisPlusUpdateWrapper {@Autowiredprivate UserMapper userMapper;@Testpublic void test1() {UpdateWrapper<User> objectUpdateWrapper = new UpdateWrapper<>();objectUpdateWrapper.gt("age", 20).like("name", "a").or().isNotNull("email").set("email", null).set("age", 90);userMapper.update(null, objectUpdateWrapper);}
}
3.LambdaQueryWrapper组装条件 

Java 8 支持以下几种方法引用的形式:

1.静态方法引用: 引用静态方法,语法为 `类名::静态方法名`。
2.实例方法引用: 引用实例方法,语法为 `实例对象::实例方法名`。
3.对象方法引用:引用特定对象的实例方法,语法为 `类名::实例方法名`。
4.构造函数引用: 引用构造函数,语法为 `类名::new`。

相比于 QueryWrapper,LambdaQueryWrapper 使用了实体类的属性引用(例如User::getName、User::getAge),而不是字符串来表示字段名,这提高了代码的可读性和可维护性 

@SpringBootTest
public class LambdaQueryWrapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void test1() {//将年龄在20到100,并且用户名中包含a或者邮箱不为Null 的用户信息修改LambdaQueryWrapper<User> objectUpdateWrapper = new LambdaQueryWrapper<>();objectUpdateWrapper.between(User::getAge, 20,100).like(User::getName, "a").or().isNotNull(User::getEmail);User user = new User(null, "test1", 98, "eefe");userMapper.update(user, objectUpdateWrapper);}
}
4.LambdaUpdateWrapper
@SpringBootTest
public class LambdaQueryWrapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void test1() {//将年龄在20到100,并且用户名中包含a或者邮箱不为Null 的用户信息修改LambdaUpdateWrapper<User> objectUpdateWrapper = new LambdaUpdateWrapper<>();objectUpdateWrapper.between(User::getAge, 20,100).like(User::getName, "a").or().isNotNull(User::getEmail).set(User::getEmail, null).set(User::getAge, 91);userMapper.update(null, objectUpdateWrapper);}
}
5.核心注解使用
(1)@TableName注解 

- 描述:表名注解,标识实体类对应的表
- 使用位置:实体类

特殊情况:如果表名和实体类名相同(忽略大小写)可以省略该注解!

其他解决方案:全局设置前缀 

mybatis-plus: # mybatis-plus的配置global-config:db-config:table-prefix: sys_ # 表名前缀字符串
(2)@TableId 注解

- 描述:主键注解
- 使用位置:实体类主键字段

属性类型必须指定默认值描述
valueString""主键字段名
typeEnumIdType.NONE指定主键类型

 IdType属性可选值:

描述
AUTO数据库 ID 自增 (mysql配置主键自增长)
ASSIGN_ID(默认)分配 ID(主键类型为 Number(Long )或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)
@TableName("sys_user")
public class User {@TableId(value="主键列名",type=主键策略)private Long id;private String name;private Integer age;private String email;
}
mybatis-plus:configuration:# 配置MyBatis日志log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:# 配置MyBatis-Plus操作表的默认前缀table-prefix: t_# 配置MyBatis-Plus的主键策略id-type: auto

在以下场景下,添加`@TableId`注解是必要的:

1. 实体类的字段与数据库表的主键字段不同名:如果实体类中的字段与数据库表的主键字段不一致,需要使用`@TableId`注解来指定实体类中表示主键的字段。


2. 主键生成策略不是默认策略:如果需要使用除了默认主键生成策略以外的策略,也需要添加`@TableId`注解,并通过`value`属性指定生成策略。

雪花算法(Snowflake Algorithm)是一种用于生成唯一ID的算法。它由Twitter公司提出,用于解决分布式系统中生成全局唯一ID的需求。

在传统的自增ID生成方式中,使用单点数据库生成ID会成为系统的瓶颈,而雪花算法通过在分布式系统中生成唯一ID,避免了单点故障和性能瓶颈的问题。

(3)@TableField

描述:字段注解(非主键)

属性类型必须指定默认值描述
valueString""数据库字段名
existbooleantrue是否为数据库表字段

 MyBatis-Plus会自动开启驼峰命名风格映射!!!

@TableName("sys_user")
public class User {@TableIdprivate Long id;@TableField("nickname")private String name;private Integer age;private String email;
}

三.高级拓展

(一)逻辑删除字段

1.概念

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

逻辑删除以后,没有真正的删除语句,删除改为修改语句!

2.实现
(1)数据库添加逻辑删除字段

数据库和实体类添加逻辑删除字段

ALTER TABLE USER ADD deleted INT DEFAULT 0 ;  # int 类型 1 逻辑删除 0 未逻辑删除
(2)实体类添加逻辑删除属性
@Data
public class User {// @TableIdprivate Integer id;private String name;private Integer age;private String email;@TableLogic//逻辑删除字段 int mybatis-plus下,默认 逻辑删除值为1 未逻辑删除 1 private Integer deleted;
}
  (3) 指定逻辑删除字段和属性值
     a.单一指定
@Data
public class User {// @TableIdprivate Integer id;private String name;private Integer age;private String email;@TableLogic//逻辑删除字段 int mybatis-plus下,默认 逻辑删除值为1 未逻辑删除 1 private Integer deleted;
}
     b.全局指定
mybatis-plus:global-config:db-config:logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)logic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
    (4)测试 
 @Testpublic void test_02() {userMapper.deleteById(1);}

(二)乐观锁实现

1.思路

乐观锁:

乐观锁的基本思想是,认为并发冲突的概率较低,因此不需要提前加锁,而是在数据更新阶段进行冲突检测和处理。乐观锁的核心思想是"先修改,后校验"。在乐观锁的应用中,线程在读取共享资源时不会加锁,而是记录特定的版本信息。当线程准备更新资源时,会先检查该资源的版本信息是否与之前读取的版本信息一致,如果一致则执行更新操作,否则说明有其他线程修改了该资源,需要进行相应的冲突处理。乐观锁通过避免加锁操作,提高了系统的并发性能和吞吐量,但是在并发冲突较为频繁的情况下,乐观锁会导致较多的冲突处理和重试操作。

悲观锁:

悲观锁的基本思想是,在整个数据访问过程中,将共享资源锁定,以确保其他线程或进程不能同时访问和修改该资源。悲观锁的核心思想是"先保护,再修改"。在悲观锁的应用中,线程在访问共享资源之前会获取到锁,并在整个操作过程中保持锁的状态,阻塞其他线程的访问。只有当前线程完成操作后,才会释放锁,让其他线程继续操作资源。这种锁机制可以确保资源独占性和数据的一致性,但是在高并发环境下,悲观锁的效率相对较低。

2.解决方案

乐观锁

a.版本号/时间戳:为数据添加一个版本号或时间戳字段,每次更新数据时,比较当前版本号或时间戳与期望值是否一致,若一致则更新成功,否则表示数据已被修改,需要进行冲突处理。

b.CAS(Compare-and-Swap):使用原子操作比较当前值与旧值是否一致,若一致则进行更新操作,否则重新尝试。

c.无锁数据结构:采用无锁数据结构,如无锁队列、无锁哈希表等,通过使用原子操作实现并发安全。

悲观锁

a.锁机制:使用传统的锁机制,如互斥锁(Mutex Lock)或读写锁(Read-Write Lock)来保证对共享资源的独占访问。
b.数据库锁:在数据库层面使用行级锁或表级锁来控制并发访问。
c.信号量(Semaphore):使用信号量来限制对资源的并发访问。

3.使用mybatis-plus数据实现乐观锁
(1) 添加版本号更新插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;
}
(2)乐观锁字段添加@Version注解

数据库也需要添加version字段

@Version
private Integer version;

ALTER TABLE USER ADD VERSION INT DEFAULT 1 ;  # int 类型 乐观锁字段

(3)正常更新使用即可
    @Testpublic void testQuick7(){//步骤1: 先查询,在更新 获取version数据//同时查询两条,但是version唯一,最后更新的失败User user  = userMapper.selectById(5);User user1  = userMapper.selectById(5);user.setAge(20);user1.setAge(30);userMapper.updateById(user);//乐观锁生效,失败!userMapper.updateById(user1);}

(三)防止全表更新和删除实现

针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除

添加防止全表更新和删除拦截器
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());return interceptor;
}
}

当发生全表删除和全表更新时,mybatis会自动阻止 

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

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

相关文章

六、Docker Swarm、Docker Stack和Portainer的使用

六、Docker swarm和Docker stack的使用 系列文章目录1.Docker swarm1.简介2.docker swarm常用命令3.docker node常用命令4.docker service常用命令5.实战案例6.参考文章 2.Docker stack1.简介3.Docker stack常用命令4.实战案例5.常见问题及调错方式1.查看报错信息并尝试解决&am…

SpringBootWeb 篇-深入了解 Redis 五种类型命令与如何在 Java 中操作 Redis

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Redis 概述 1.1 Redis 下载与安装 2.0 Redis 数据类型 3.0 Redis 常见五种类型的命令 3.1 字符串操作命令 3.2 哈希操作命令 3.3 列表操作命令 3.4 集合操作命令 …

7-43 排列问题

排列问题 分数 10 全屏浏览 切换布局 作者 雷丽兰 单位 宜春学院 全排列问题 输出自然数1至n中n个数字的全排列&#xff08;1≤n≤9&#xff09;&#xff0c;要求所产生的任一数字序列中不允许出现重复的数字。 输入格式: 一个自然数 输出格式: 由1到n中n个数字组成的…

Tessy学习系列(三):单元测试——官方例程isValueInRange

一、工程创建 &#xff08;1&#xff09;新建工程 注意&#xff1a;工程名称以及路劲不能包含空格和中文 &#xff08;2&#xff09;新建测试集与单元测试模块 新建测试集 新建单元测试模块 设置测试模块为单元测试模块并选择GNU GCC编译器如果需要其他的编译器&#xff0c;…

关于选择,关于处事

一个人选择应该选择的是勇敢&#xff0c;选择不应该选择的是无奈。放弃&#xff0c;不该放弃的是懦夫&#xff0c;不放弃应该放弃的是睿智。所以&#xff0c;碰到事的时候要先静&#xff0c;先不管什么事&#xff0c;先静下来&#xff0c;先淡定&#xff0c;先从容。在生活里要…

【线性代数】向量空间,子空间,向量空间的基和维数

向量空间 设V为n维向量的集合&#xff0c;如果V非空&#xff0c;且集合V对于向量的加法以及数乘两种运算封闭&#xff0c;那么就称集合V为向量空间 x&#xff0c;y是n维列向量。 x 向量组等价说明可以互相线性表示 向量组等价则生成的向量空间是一样的 子空间 例题18是三位向…

Docker Swarm持久化

Docker Swarm持久化 1 简介 Docker Swarm持久化有bind、volume和NFS三种方式&#xff0c;bind和volume两种方式适合挂载单个宿主机&#xff0c;不适合集群&#xff1b;NFS适合集群服务&#xff0c;但需要安装NFS系统。 注意&#xff1a;Docker Swarm需要先安装集群。 由Doc…

python-数字黑洞

[题目描述] 给定一个三位数&#xff0c;要求各位不能相同。例如&#xff0c;352是符合要求的&#xff0c;112是不符合要求的。将这个三位数的三个数字重新排列&#xff0c;得到的最大的数&#xff0c;减去得到的最小的数&#xff0c;形成一个新的三位数。对这个新的三位数可以重…

【数据结构】【版本1.0】【线性时代】——顺序表

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、顺序表的概念1.1 最基础的数据结构&#xff1a;数组1.2 数组与顺序表的区别 二、静态顺序表三、动态…

error while loading shared libraries 找不到动态库问题如何解决

在使用 c 或 c 开发应用时&#xff0c;在启动程序时&#xff0c;有时会遇到这个错误&#xff0c;找不到动态库。这个时候&#xff0c;我们使用 ldd 来查看&#xff0c;发现可执行文件依赖的动态库显示为 not found。 1 实验代码 使用如下 3 个文件做实验。 hello.h 中声明了函…

【Vue】修改数量

文章目录 底部总价展示完整代码 注意&#xff1a;前端 vuex 数据&#xff0c;后端数据库数据都要 注册点击事件 页面中dispatch action 提供action函数 提供mutation处理函数 底部总价展示 提供getters 动态渲染 完整代码 main.js import Vue from vue import App from…

Linux:基础开发工具

文章目录 Linux 软件包管理器 yum什么是软件包关于rzsz查看软件包安装软件卸载软件安装扩展源 Linux 编辑器 vimvim的基本概念正常/普通/命令模式(Normal mode)插入模式(Insert mode)底行模式(last line mode) vim的基本操作[命令模式]切换至[插入模式][插入模式]切换至[命令模…

【CW32F030CxTx StartKit开发板】开发资料

本来是参加21ic的评测活动&#xff0c;不知道为什么评测文章一直被提示有不良内容&#xff0c;所以只好先在此记录一下相关的资料。 此次测试的是CW32F030CxTxStartKit 评估板。该开发板为用户提供一种经济且灵活的方式使用 CW32F030CxTx 芯片构建系统原型&#xff0c;可进行性…

激活乡村振兴新动能:推动农村产业融合发展,打造具有地方特色的美丽乡村,实现乡村全面振兴

目录 一、推动农村产业融合发展 1、农业产业链条的延伸 2、农业与旅游业的结合 二、挖掘地方特色&#xff0c;打造美丽乡村 1、保护和传承乡村文化 2、发展特色农业 三、加强基础设施建设&#xff0c;提升乡村品质 1、改善农村交通条件 2、提升农村水利设施 四、促进…

吴恩达2022机器学习专项课程C2W2:2.23 选修_反向传播算法的工作原理(什么是导数图计算大型神经网络)

目录 引言一.导数的计算1.epsilon与导数的关系2.其它导数符号形式3.导数小结 二.小型神经网络的计算图1.什么是计算图&#xff08;前向传播过程&#xff09;2.反向传播计算过程3.验证反向传播的计算结果4.为什么用反向传播计算导数&#xff1f; 三.扩大神经网络的计算图1.计算反…

笔记本充电出现了问题。

不知道为什么。电池充电图片一直显示的空。谁能救救我&#xff01;

C51学习归纳9 --- I2C通讯学习(重点)

首先&#xff0c;我自己学习过以后的直观感觉&#xff0c;通信协议是单片机的灵魂之一&#xff0c;只有规定好了通信协议我们才能够正确的接收到信息&#xff0c;才能实现更加深入的研究。所以这一部分是需要好好学习的。 本节借助一个可存储的芯片AT24C02&#xff0c;进行在I2…

C语言怎样初始化图形模式?

一、问题 在C语⾔中&#xff0c;initgraph( ) 函数⽤于初始化图形模式。初始化时&#xff0c;那么多参数都是⼲什么的&#xff1f;怎样设置&#xff1f; 二、解答 initgraph( ) 函数⽤于初始化图形模式&#xff0c;其语法格式如下。 void far initgraph(int far * gdriver, i…

对象存储OSS 客户端签名直传的安全风险和解决方法

1. 前言 阿里云对象存储OSS&#xff08;Object Storage Service&#xff09;是一款海量、安全、低成本、高可靠的云存储服务&#xff0c;可提供99.9999999999%&#xff08;12个9&#xff09;的数据持久性&#xff0c;99.995%的数据可用性。多种存储类型供选择&#xff0c;全面…

11.链表

数组的分类&#xff1a;便于遍历 静态数组&#xff1a;int arr[10]数据过多造成空间溢出&#xff0c;数据过小空间浪费 动态数组&#xff1a;malloc calloc realloc 合理利用空间不能快捷的插入或删除数据&#xff08;会涉及到大量的数据移动&#xff09; 知识点一&#xff1…