Mybatis-plus学习(基于版本3.0.5)

news2025/1/13 7:42:38

文章目录

  • 一.概念
    • 1.1 简介
    • 1.2 特性
  • 二.快速入门
  • 三.CRUD扩展
    • 3.1 Insert插入
    • 3.2 主键生成策略
    • 3.3 Update更新
    • 3.4 自动填充
    • 3.5 乐观锁
    • 3.6 查询操作
    • 3.7 删除操作
    • 3.8 性能分析插件(新版本的Mybatis-plus已将此插件移除)
    • 3.9 条件构造器
    • 3.10 代码生成器

一.概念

1.1 简介

Mybatisplus从字面上面理解时Mybatis的加强版,它可以大大节省我们大量的工作时间,所有的增删改查代码它都可以在mybatisplus中自动的完成,其本质上上Mybatis的一个增强工具,在Mybatis的基础上只做增强不做改变,为简化开发,提高效率而生。
在这里插入图片描述

1.2 特性

  1. 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  2. 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作(BaseMapper)
  3. 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求(以后的简单的crud操作不用自己编写)
  4. 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
    支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  5. 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
    支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  6. 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(自动生成分页)
  7. 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
    分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  8. 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
    内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

二.快速入门

使用官方提供的快速开始文档

  1. 创建数据库mybatisplus
  2. 创建表user插入数据
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');
  1. 创建一个springboot项目
  2. 导入依赖
<!--        mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
<!--        lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
<!--        mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>
  1. 连接数据库
  • 配置SpringBoot配置文件
spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/mybatisplus?userSSL=false&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver
  1. 编写pojo类(与传统使用Mybatis一样)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class user {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
  1. 配置Dao层

使用mybatisplus之后只需要在对应的mapper上面继承基本的类BaseMapper即可(不需要像Mybatis那样繁琐)。到此所有的CRUD已经Mybatisplus帮我们自动编写完成十分方便(当然我们也可以在这里面定义自己的代码)。

@Repository //代表这个接口是Dao层的
public interface UserMapper extends BaseMapper<User> {
}

  • 在启动类上配置mapper扫描(此时dao层就配置完毕了)
@MapperScan("com.chailong.getspring.mapper")  //扫描mapper的文件夹
@SpringBootApplication
public class GetspringApplication {

    public static void main(String[] args) {
      SpringApplication.run(GetspringApplication.class, args);
    }
  • 在测试类中测试
@SpringBootTest
class GetspringApplicationTests {
    @Autowired
    private UserMapper userMapper; //注入usermapper的bean
    @Test
    void contextLoads() {
        //seleclist的参数是一个wrapper(条件构造器)
        List<user> userList=userMapper.selectList(null);//查询全部
        for (user user1 : userList) {
            System.out.println(user1);
        }
    }
}

运行结果:
在这里插入图片描述
8. 配置日志

在前面的操作过程中我们是具体看不到我们的sql语句的,为了能在控制台看到我们的sql语句,我们需要对日志进行配置

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

结果:
在这里插入图片描述

三.CRUD扩展

3.1 Insert插入

  1. 编写插入代码
   @Test
    void testInsert() {
        user usernew=new user();
        usernew.setName("chailong");
        usernew.setAge(11);
        usernew.setEmail("2012126846@qq.com");
        int result=userMapper.insert(usernew);
        System.out.println(result);
    }

结果:(发现自动插入了id)
在这里插入图片描述
2. 问题

思考这里为什么会自动生成唯一ID?
这就要涉及到分布式系统唯一id生成中的雪花算法

3.2 主键生成策略

  1. 雪花算法

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证ID唯一性。

  1. 使用@TableId注解可以配置主键生成策略(下面是常见的策略)

默认策略是ID_WORKER全局唯一ID

@Data
@AllArgsConstructor
@NoArgsConstructor
public class user {
    @TableId(type = IdType.ID_WORKER )
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

在这里插入图片描述
3. 主键自增策略

  1. 在实体类字段上配置@TableId(type=IdType.AUTO)
  2. 勾选Mysql数据库中ID自增选项
  1. 其它自增策略源码解释
public enum IdType {
    AUTO(0), //数据库id自增
    NONE(1),//未设置主键
    INPUT(2),//手动输入(数据库里面自己填)
    ID_WORKER(3),//默认全局唯一id
    UUID(4),//全局唯一id
    ID_WORKER_STR(5);//ID_worker的字符串表示法
}

3.3 Update更新

测试类代码

   @Test
    void testUpdate() {
        user usernew=new user();
        usernew.setId(11);
        usernew.setName("jakiechai");
        usernew.setAge(11);
        usernew.setEmail("2012126846@qq.com");
        int i=userMapper.updateById(usernew);
        System.out.println(i);
    }

结果:
在这里插入图片描述
可以发现mybatis-plus帮我们实现了自动动态配置,这就需要讲到mybatis-plus的自动填充技术,下面介绍自动填充技术。

3.4 自动填充

问题提出:在创建数据表中我们有些参数是不希望用户去手动填充的而是希望系统帮我们去自动填充(如表创建时间和表修改时间等)。阿里巴巴开发手册规定几乎所有数据表字段都必须要有一个gmt_create(创建时间)和gmt_modified(修改时间),而这两个参数是需要系统自动填充的;这就涉及到了自动填充技术。

  1. 数据库级别自动填充(实际生活中不建议这种方法)

在表中新增字段创建时间和修改时间设置默认值即可(修改表字段即可,注意pojo对应属性也要更改)

  1. 代码级别自动填充
  1. 删除数据库默认值

在这里插入图片描述

  1. 实体类属性上加入相关注解
    在TableField接口中有一个fill函数用于属性值的自动填充
    FieldFill fill() default FieldFill.DEFAULT;
    FieldFill的值表示填充的方法

public enum FieldFill {
    DEFAULT,  //默认不填充
    INSERT,   //插入时填充
    UPDATE,   //更新时填充
    INSERT_UPDATE; //更新或插入时填充
    }

然后在类属性上加入@TableField注解

@Data
@AllArgsConstructor
@NoArgsConstructor
public class user {
    @TableId(type = IdType.AUTO )
    private int id;
    private String name;
    private Integer age;
    private String email;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

  1. 编写处理器来处理注解
  1. 在主目录下建立一个Handler包,专门用来放SpringBoot项目的处理器,编写处理器代码
@Slf4j  //使用日志
@Component  //处理器加入到ioc容器中
public class MyMetaObjectHandler implements MetaObjectHandler {
    //实现插入时自动填充
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill.....");
        //setFieldValByName(字段名,字段值,metaObject)
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
        log.info("insert over");
    }
    //实现更新时自动填充
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill.....");
        //setFieldValByName(字段名,字段值,metaObject)
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
        log.info("update over");
    }
}

  1. 测试类代码
    @Test
    void testInsert() {
        user usernew=new user();
        usernew.setName("menglei");
        usernew.setAge(11);
        usernew.setEmail("2012126846@qq.com");
        int result=userMapper.insert(usernew);
        System.out.println(result);
    }

运行结果:数据库插入成功(字段也帮我们自动填充了)
在这里插入图片描述

3.5 乐观锁

  1. 简介

所谓的乐观锁,其实主要就是一种思想,因为乐观锁的操作过程中其实没有没有任何锁的参与,乐观锁只是和悲观锁相对,严格的说乐观锁不能称之为锁。所以要了解乐观锁的概念,通常与悲观锁对比起来看才更好理解,下面我们就通过乐观锁与悲观锁的对比来更好的理解乐观锁。乐观锁总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,只在更新的时候会判断一下在此期间别人有没有去更新这个数据。悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞,直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。

  1. 乐观锁实现方式
  1. 取出记录时获取当前version
  2. 更新时带上这个version
  3. 执行更新时,set version=nerVersion where version =oldVersion
  4. 如果version不对,就更新失败
  1. 举例说明
    假设两个线程A和B都在执行更新操作:
//A执行更新
 update user set name="kuanshen",version=version+1
 where id=2 and version =1
//B执行更新
 update user set name="kuanshen",version=version+1
 where id=2 and version =1

假设B先完成了更新,version被改变,此时A就会更新失败,这就是乐观锁实现线程安全的机制
4. 使用Mybatis-plus的乐观锁插件

  1. 给数据表中加入version字段,并设置默认值为1

在这里插入图片描述

  1. 实体类同步,并给属性上加入乐观锁注解

在这里插入图片描述

  1. 在Handler文件下编写乐观锁的组件
@Configuration   //声明这是一个配置类
@EnableTransactionManagement  //事务
public class MybatisplusConfig {
    //注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

}
  1. 测试乐观锁
  • 单线程情况
    @Test
    void testOptimisticLocker(){
        //1查询用户信息
        user usermy=userMapper.selectById(1);
        //2.修改用户信息
        usermy.setName("mike");
        usermy.setAge(11);
        usermy.setEmail("jake.com");
        //3.更新用户信息
        userMapper.updateById(usermy);
    }

运行结果:更新成功version加1(单线程不存在现场安全问题,一定会更新成功)
在这里插入图片描述

  • 多线程情况模拟
 @Test
    void testOptimisticLocker(){
       //线程1(准备更新但是还没更新)
        user usermy=userMapper.selectById(1);
        usermy.setName("mike2");
        usermy.setAge(11);
        usermy.setEmail("jake.com");

        //线程2(插队在线程1之前执行了更新)
        user usermy2=userMapper.selectById(1);
        usermy2.setName("mike1");
        usermy2.setAge(11);
        usermy2.setEmail("mary.com");
        userMapper.updateById(usermy2);//线程2的更新操作
        userMapper.updateById(usermy);//线程1的更新操作(如果没有乐观锁就会把线程2更新的值直接覆盖掉)
    }

结果:乐观锁机制使得线程1没有更新
在这里插入图片描述

3.6 查询操作

  1. 根据Mybatis-plus提供的接口直接用即可(比如下面根据ID查询多个用户)
  @Test
    void testquery(){
        System.out.println(userMapper.selectBatchIds(Arrays.asList(1,2,3)));
    }

结果:
在这里插入图片描述
2. 分页查询

在以前的ssm项目中几乎使用的都是原始的limit分页方式或者使用pageHelper等第三方插件,Mybaits-plus也为开发者准备了分页插件,开发直接使用即可,十分方便

  1. 配置分页组件(在配置类中加入分页的Bean就行)
  @Bean
    public PaginationInterceptor pageInationInterceptor(){
        return new PaginationInterceptor();
    }
  1. 使用Page对象进行分页
   @Test
    void testPage(){
        Page<user> page=new Page<>(2,5);//当前页第2页,每页5条数据
        userMapper.selectPage(page,null);//null是给条件查询器参数(这里不使用)
        page.getRecords().forEach(System.out::println);
    }

结果:
在这里插入图片描述

3.7 删除操作

  1. 根据id删除用户
 @Test
    void testDeleteById(){
       int result=userMapper.deleteById(1);
        System.out.println(result);
    }

结果:
在这里插入图片描述
2. 逻辑删除

物理删除:从数据库中直接删除
逻辑删除:并没有从数据库中删除而是通过一个变量让其不能使用(达到了所谓删除的目的),用于防止数据的丢失,相当于回收站的作用

  1. 增加一个删除标记字段在数据库中

在这里插入图片描述

  1. pojo增加属性并使用注解
@TableLogic
    private int flage;
  1. 配置逻辑删除组件
@Bean
    public ISqlInjector sqlInjector(){
        return  new LogicSqlInjector();
    }
  1. 配置文件中配置逻辑删除
mybatis-plus:
  global-config:
    db-config:
      logic-delete-value: 1
      logic-not-delete-value: 0
  1. 测试逻辑删除
  @Test
    void logicdelet(){
       userMapper.deleteById(2); //逻辑删除2号用户
    }

结果:数据并没有删除(但flage变成了1即数据已经被逻辑删除了)
在这里插入图片描述
然后测试一下是否能查询到逻辑删除的数据:

 @Test
    void testquery(){
        System.out.println(userMapper.selectById(2));
    }

结果:查询不到
在这里插入图片描述

3.8 性能分析插件(新版本的Mybatis-plus已将此插件移除)

慢sql:慢SQL指的是MySQL慢查询,是运行时间超过long_query_time值的SQL。真实的慢SQL通常会伴随着大量的行扫描、临时文件排序或者频繁的磁盘flush,直接影响就是磁盘IO升高,让正常的SQL变成了慢SQL,大面积执行超时。

在实际操作中我们会经常遇到一些慢sql,如何找出这些慢sql我们的Mybatis-plus也提供了 相应的插件:
性能分析插件:
性能分析拦截器,用于输出每条SQL语句及其执行时间。SQL性能执行分析,开发环境使用,超过指定时间停止运行,有助于发现问题。

  1. 编写性能分析插件
    //SQL执行效率插件
    @Bean
    @Profile({"dev","test"}) //设置 dev test 环境开启,保证我们的效率
    public PerformanceInterceptor performanceInterceptor(){
        PerformanceInterceptor  performanceInterceptor=new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(1);  //设置sql的最大执行时间为1ms
        performanceInterceptor.setFormat(true);//是否开启格式化支持
        return performanceInterceptor;
    }
  • 在spring配置文件中配置环境为dev或者test环境
spring:
  profiles:
    active: dev
  1. 测试插件
  @Test
    void testPage(){
        Page<user> page=new Page<>(2,5);
        userMapper.selectPage(page,null);
        page.getRecords().forEach(System.out::println);
    }

结果:sql运行时间为14ms超过了规定的时间所以执行失败
在这里插入图片描述

3.9 条件构造器

在前面使用的mybatis-plus提供的sql函数接口中,我们会发现我们把wrapper这个参数设置为了null,wrapper就是我们的条件构造器,用于写一些复杂的sql

  1. 使用wrapper进行复杂的查询操作:
 @Test
    void contextLoads(){
        //查询name不为空的用户,并且邮箱不为空的用户,年龄>21的用户
        QueryWrapper<user> wrapper=new QueryWrapper<user>();  //创建条件构造器
        wrapper.isNotNull("name");  //name不为空的查询条件
        wrapper.isNotNull("email");  //邮箱不为空
        wrapper.ge("age",12); //年龄大于12
        userMapper.selectList(wrapper).forEach(System.out::println);
    }

结果:
在这里插入图片描述

    @Test
    void contextLoads(){  //查询名字为menglei的用户
        //查询name不为空的用户,并且邮箱不为空的用户,年龄>21的用户
        QueryWrapper<user> wrapper=new QueryWrapper<user>();  //创建条件构造器
        wrapper.eq("name","menglei");
        userMapper.selectOne(wrapper);
    }

结果:
在这里插入图片描述
官网可以查看更多的使用方法

3.10 代码生成器

代码自动生成:AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

 public static void main(String[] args) {
        //构建一个代码自动生成器对象
        AutoGenerator autoGenerator=new AutoGenerator();
        //配置策略
        //1全局配置
        GlobalConfig gc=new GlobalConfig();
        String property = System.getProperty("user.dir"); //获取用户目录
        gc.setOutputDir(property+"/src/src/main/java");//代码文件的生成路径
        gc.setAuthor("chailong"); //设置作者
        gc.setFileOverride(false);//是否覆盖
        gc.setServiceName("%sService");//去service的i前缀
        gc.setIdType(IdType.ID_WORKER); //设置Id自增
        gc.setDateType(DateType.ONLY_DATE);//设置日期类型
        gc.setSwagger2(true);//设置swagger
        autoGenerator.setGlobalConfig(gc);

        //2. 设置数据源
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mybatisplus");
        dataSourceConfig.setUsername("root");
        dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");
        dataSourceConfig.setPassword("123456");
        dataSourceConfig.setDbType(DbType.MYSQL);
        autoGenerator.setDataSource(dataSourceConfig);

        //3.设置包
        PackageConfig packageConfig = new PackageConfig();
        packageConfig.setModuleName("blog");
        packageConfig.setParent("com.chailong.getspring");
        packageConfig.setEntity("entity");
        packageConfig.setMapper("mapper");
        packageConfig.setService("service");
        packageConfig.setController("controller");
        autoGenerator.setPackageInfo(packageConfig);

        //4.策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("user"); //设置映射的表名
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);//自动生成lombok
        strategy.setLogicDeleteFieldName("flage"); //设置逻辑删除名字
        //4.设置自动填充
        TableFill create_time = new TableFill("create_time", FieldFill.INSERT_UPDATE);
        TableFill update_time = new TableFill("update_time", FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> arrayList = new ArrayList<>();
        arrayList.add(create_time);
        arrayList.add(update_time);
        strategy.setTableFillList(arrayList);

        //乐观锁
        strategy.setVersionFieldName("version");
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true);
        autoGenerator.setStrategy(strategy);

        autoGenerator.execute();//执行
    }

运行结果:

  1. 生成的新的java目录(原来的内容没有被覆盖)
    在这里插入图片描述

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

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

相关文章

Transformer合集3

太多了 我都累了 这都第4了 这次先是关于他的小样本目标检测 , 用很少的训练示例检测新目标 小样本目标检测 论文地址&#xff1a; https://openaccess.thecvf.com/content/CVPR2022/papers/Han_Few-Shot_Object_Detection_With_Fully_Cross-Transformer_CVPR_2022_paper.…

docker安装influxdb及备份恢复

influxdb安装influxdb1&#xff0c;拉取镜像2&#xff0c;创建目录并进入到目录内3&#xff0c;创建influxdb容器服务4&#xff0c;访问&#xff1a;ip8086备份恢复influxdb数据准备1.1 创建用户&#xff0c;填入组织&#xff0c;桶信息1.2&#xff0c;给桶添加点数据1&#xf…

ansible部署lnmp架构

环境准备&#xff1a; 主机名IP服务系统ansible192.168.160.131ansibleCentOS-8.5nginx192.168.160.132nginxCentOS-8.5mysql192.168.160.137mysqlCentOS-8.5php192.168.160.139phpCentOS-8.5 1、生成私钥&#xff0c;对另外三台主机进行免密登入 [rootansible ~]# ssh-keyge…

【单片机毕业设计】【mcuclub-jj-007】基于单片机的门铃的设计

最近设计了一个项目基于单片机的门铃&#xff0c;与大家分享一下&#xff1a; 一、基本介绍 项目名&#xff1a;门铃 项目编号&#xff1a;mcuclub-jj-007 单片机类型&#xff1a;STC89C52、STM32F103C8T6 具体功能&#xff1a; 1、通过人体热释电检测是否有人&#xff0c;当…

Java --- 创建SpringMVC项目

目录 一、什么是MVC 二、什么是SpringMVC 三、SpringMVC的特点 四、创建SpringMVC项目 4.1、开发环境 4.2、创建maven工程 4.3、配置web.xml文件 4.4、创建请求控制器 4.5、配置springMVC.xml文件 4.5、访问首页面 4.6、访问指定页面 一、什么是MVC MVC是一种软件架…

C++:C++的IO流

while (scanf("%s", buff) ! EOF)如何终止&#xff1f; 答&#xff1a;ctrl z换行 是规定&#xff0c;ctrl c 是发送信号杀死进程&#xff08;一般不建议ctrl c&#xff09;。 int main() {string str;while (cin >> str) // operator>>(cin, str){cou…

K_A01_001 基于单片机驱动WS2812 点灯流水灯 0-9显示

目录 一、资源说明 二、基本参数 三、通信协议说明 WS2812时序: 代码: 四、部分代码说明 1、接线说明 2、主函数 五、相关资料链接 六、数字提取格式 七、视频效果展示与资料获取 八、项目所有材料清单 九、注意事项 十、接线表格 一、资源说明 单片机型号 测试条件 模…

【一起学习数据结构与算法】优先级队列(堆)

目录一、什么是优先级队列&#xff1f;二、堆 (heap&#xff0c;基于二叉树)2.1 什么是堆&#xff1f;2.2 堆的分类2.3 结构与存储三、堆的操作3.1 堆创建3.2 插入元素3.3 弹出元素四、用堆模拟实现优先级队列五、堆的一个重要应用-堆排序六、经典的TOPK问题6.1 排序6.2 堆一、…

如何用两个晚上教女生学会Python

文章目录安装、需求引导和开发模型命令行计算器用温度指导穿衣VS Code 和女孩子的衣柜用遍历来挑选衣物交互课后作业事情的起因是这样的&#xff0c;知乎上有个妹纸加我&#xff0c;说要相亲。尽管我欣喜若狂&#xff0c;但恰巧在外出差&#xff0c;根本走不开。妹纸于是说要不…

自动化和半自动矢量化提取地物矢量轮廓

假期愉快&#xff08;这个假期加班了没&#xff1f;图片&#xff09;&#xff01;今天小助手来分享关于自动化和半自动化的矢量提取&#xff0c;使用的软件都是我们常用的软件。一是使用Global Mapper对遥感影像或矢量底图进行自动提取&#xff0c;二是基于天地图矢量底图使用A…

阶段性总结 | C语言

… &#x1f333;&#x1f332;&#x1f331;本文已收录至&#xff1a;技术之外的往事 更多知识尽在此专栏中&#xff01; &#x1f389;&#x1f389;&#x1f389;欢迎点赞、收藏、关注 &#x1f389;&#x1f389;&#x1f389;回顾过去 各位CSND的小伙伴们大家好&#xf…

C · 进阶 | 慎看!深剖文件操作,怕你停不下

啊我摔倒了..有没有人扶我起来学习.... 目录前言一、 什么是文件1.1 程序文件1.2 数据文件1.3 文件名二、文件的打开和关闭2.1 文件指针2.2 文件的打开和关闭三、文件的顺序读写3.0 有必要解释一下*3.1 fputc3.2 fgetc3.3 fprintf3.4 fscanf3.4.1来个小总结&#xff08;这里忽略…

双非本23秋招之路-从考研跑路到某安全大厂(无实习、项目)

文章目录双非本23秋招之路-从考研跑路到某安全大厂&#xff08;无实习、项目&#xff09;一、自我介绍二、简历准备三、刷题四、八股文五、项目方面六、关于实习七、面试方面八、秋招路程九、简历投递十、面经分享双非本23秋招之路-从考研跑路到某安全大厂&#xff08;无实习、…

springboot+jsp新闻发布投稿系统

本文采用JSP技术构建的一个管理系统&#xff0c;实现了一个新闻发布系统。新闻发布系统的主要实现功能包括&#xff1a;管理员&#xff1a;首页、个人中心、用户管理 、新闻分类管理 、新闻信息管理、新闻投稿管理、论坛管理、我的收藏管理、投诉建议管理、系统管理。前台首页&…

Python编程 print输出函数

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.输入与输出 1.print&#xff08;&#xff09;输出函数 2.sep 3.en…

【MySQL数据库和JDBC编程】第三章-第一节:MySQL的增删查改基础篇

文章目录一&#xff1a;INSET新增二&#xff1a;SELECT查询&#xff08;1&#xff09;全列查询&#xff08;2&#xff09;指定列查询&#xff08;3&#xff09;查询字段为表达式&#xff08;4&#xff09;起别名&#xff08;5&#xff09;去重&#xff08;DISTINCT&#xff09;…

微信小程序request:fail报错(包括不执行fail回调问题)

微信小程序request:fail报错&#xff08;包括不执行fail回调的问题&#xff09;1. 不执行fail回调的问题2. request:fail报错原因2.1 小程序未配置域名导致的错误2.2 微信小程序使用的服务器环境不支持TLS1.22.3 使用的SSL证书不信任2.4 SSL证书证书链缺乏2.5 域名未备案&#…

使用Spring框架进行Web项目开发(初级)

目录 前言 1. 为什么常规的Spring框架不适合Web项目呢&#xff1f; 2. 如何在Spring框架中创建容器&#xff1f; 3. Spring框架开发Web项目的步骤 3.1 创建maven项目 3.2 添加相应的依赖 3.3 在webapp目录下的web.xml中注册监听器 3.4 在webapp文件夹下的web.xml中配置…

【信息科学技术与创新】自然语言处理 NLP 计算机与智能 课程总结思考

深入了解 NLP 及课程总结反思 摘要 自然语言处理的历史发展自然语言处理的方法与相关应用关于数据智能科学技术导论这门课程的总结反思 Navigator深入了解 NLP 及课程总结反思一、自然语言处理的历史发展二、自然语言处理的方法与相关应用三、关于数据智能科学技术导论这门课…

【C++初阶】日期类实现、const成员函数、取地址及const取地址操作符重载

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;日期类的代码实现、const成员函数的概念和作用、取地址及const取地址操作符重载 &#x1f6a2;&#x1f6a2…