MyBatis-Plus学习总结

news2024/9/23 3:20:57

目录

1.MyBatis-Plus介绍

2.第一个MyBatis-Plus程序

3.配置日志输出

4. 主键生成策略

4.1 ID_WORKER -- 雪花算法

4.2 主键生成策略 -- 详情

5. 自动填充

6.MyBatis-Plus的CRUD

6.1 insert -- 插入

6.2 delete -- 删除

6.3 update -- 更新

6.4 select -- 查询

7. 逻辑删除插件

8. 乐观锁组件

9. 分页查询组件

10. 性能分析组件

11. wrapper条件查询器

12. 代码自动生成器


1.MyBatis-Plus介绍

看到plus我们应该大致能够了解到这是一个Mybatis的增加版本。相较于传统的MyBatis开发,它在诸多方面有了质的提升,例如:

  1. 提供了更为强大的CRUD策略,我们不必再去书写繁琐的sql语句;
  2. 内置分页插件,不必你再去手工limit;
  3. 性能分析插件、全局拦截插件、无侵入、损害小......

我们可以将MyBatis和MyBatis-Plus视为“彼此之间最好的搭档,正所谓:'基友搭配,效率翻倍!'”。接下来依赖来探索下MyBatis-Plus的魔力吧!

2.第一个MyBatis-Plus程序

学好一个框架的最优策略,我认为是先从整体上来学会如何正确的进行基础的运用,才能知其底层,继而行云流水,倒背如流。与传统的MyBatis发挥的作用类似,MyBatis-Plus作为一种持久层的与数据库进行交互的框架,我们得现有一张数据库表来进行操作。接下来我们来一块实现这个小程序:

3.配置日志输出

默认情况下,MyBatis-Plus的执行是不会在任何地方输出执行的日志信息的,而在开发中,为了更高效的发现和出现可能出现的运行问题,查看程序的日志是必不可少的,MyBatis-Plus通过以下配置项配置日志输出:

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

4. 主键生成策略

不知道大家有没有发现,在上边我们插入的数据中并没有设置插入数据的主键id信息,而我们现在来查看下数据库中插入的数据:

这就要谈谈MyBatis-Plus的主键生成策略了,默认情况下,它的主键生成策略是 ID_WORKER —— 全球唯一ID。这也是为什么会出现这个数字ID的原因。在每次插入数据时,Mybatis-Plus都会生成一个唯一的主键ID。那么Mybatis-Plus是如何保证这个ID的唯一性呢?

4.1 ID_WORKER -- 雪花算法

我们知道,生成随机值的方式有很多种,像UUID,Redis生成、Zookeeper生成等等,那为什么MyBatis-Plus要使用雪花算法来实现主键ID的生成呢?对了,唯一性!雪花算法能够在保证随机性的同时相较于其他的随机算法能够更加提高唯一ID生成的概率。接下来我们来看看雪花算法是如何生成一个随机唯一ID的:

4.2 主键生成策略 -- 详情

Mybatis-Plus提供了6种主键的生成策略:


 默认情况下使用的主键生成策略是全局唯一ID(ID_WORKER生成),这个在上面已经体验过了。接下来我们来使用下它的AUTO自增生成和INPUT手动输入生成:

5. 自动填充

为了更好的学习MyBatis-Plus关于时间字段的生成策略,我们先修改一下表的结构:


在之前的项目开发中,对于数据库中相关时间字段的值的插入和更新,我往往是采用手动创建插入的方式来进行处理的,


后来阅读了阿里巴巴的开发者手册,我感觉到之前的处理方式效率太低了。为了解决这种问题,MyBatis-Plus为我们提供了数据库表中时间相关的字段的生成策略,来帮助我们更高效的实现持久层和数据库表之间的交互过程。 接下来一起来看下怎么实现吧:

 

6.MyBatis-Plus的CRUD

通过上面的学习,我们已经知道,Mybatis-Plus已经为我们实现好了CRUD的操作方法,那么对于不同方法的使用细节,复杂查询SQL的组装向条件查询,分页查询以及新增、修改删除数据应该如何去调用呢?我们知道,自己创建的mapper接口需要去继承MyBatis-Plus的BaseMapper<T>接口,而继承这个接口就是为了能够调用其中的接口方法继而动态绑定到这个持久层框架已经为我们提供好的操作方法中,我们来探索一下这个接口:


 6.1 insert -- 插入

对于插入来说,很直接。我们只需要调用自己创建的继承自BaseMapper<T>接口中的insert方法并传入携带数据的实体对象即可完成,如下:

@Test
@Transactional
void testInsert() {
    User user = new User();
    user.setAge(20);
    user.setName("白小帅");
    user.setEmail("bxshuai@yeah.net");
    userMapper.insert(user);
    //执行的sql
    //INSERT INTO user ( name, age, email, create_time, update_time ) VALUES ( '白小帅', 20, bxshuai@yeah.net, now(), now());
}

6.2 delete -- 删除

对于删除来说,这个框架给我们提供了很多种删除的方式,比如根据主键ID删除、根据指定条件删除等等,我们一起来看下:

@Test
@Transactional
void testDelete() {
    userMapper.deleteById(1679119918046838790L);    //指定id删除
    //执行的sql: delete from user where id=1679119918046838790L;
    // 或者
    userMapper.deleteBatchIds(Arrays.asList(1, 2, 3));    //根据id批量删除
    //执行的sql:delete from user where id in (1,2,3);
    // 或者
    HashMap<String, Object> wrapperMap = new HashMap<>();
    wrapperMap.put("name", "白小帅");  //构造where条件
    userMapper.deleteByMap(wrapperMap);
    //执行的sql:delete from user where name='白小帅';
}

6.3 update -- 更新

@Test
void testUpdate() {
    User user = new User();
    user.setId(1679119918046838791L);
    user.setEmail("bxsxiao@sina.com");
    userMapper.updateById(user);
    //执行的sql:
    //UPDATE user SET email=bxsxiao@sina.com, update_time=2023-07-13 15:16:49.166 WHERE id=1679119918046838791
}

6.4 select -- 查询

Mybatis-Plus的查询有很多种方式,我们总结了以下几种,其原理都是相同的,实现也类似。无非都是通过修改查询条件来实现的。

@Test
void testSelect() {
    List<User> users = userMapper.selectList(null);//无条件查询所有数据
    users.forEach(System.out::println);
    //执行的SQL:SELECT id,name,age,email,create_time,update_time FROM user


    User user = userMapper.selectById(2);
    System.out.println(user);
    //执行的SQL:SELECT id,name,age,email,create_time,update_time FROM user WHERE id=2;

    HashMap<String, Object> wrapperMap = new HashMap<>();
    wrapperMap.put("name", "白小帅");
    wrapperMap.put("email", "bxsxiao@sina.com");
    List<User> users1 = userMapper.selectByMap(wrapperMap);
    users1.forEach(System.out::println);
    //执行的SQL:SELECT id,name,age,email,create_time,update_time FROM user WHERE name = '白小帅' AND email = 'bxsxiao@sina.com'; 
}

7. 逻辑删除插件

不知道大家有没有发现,csdn给我们提供了blog的回收站功能。包括还有像某些网站的上你删除的评论信息仍然能够被后台管理员看到。向这种功能的实现就称为数据的逻辑删除。与普通删除不同的是,普通删除直接将数据从数据库中移除了;而逻辑删除在数据库表中新增了一个逻辑删除字段,例如当这个逻辑删除字段值为0代表未删除,值为1代表已删除。


 使用了Mybatis-Plus后,我们就不用再手动编写sql来实现逻辑删除了,让我们一起来看下MyBatis-Plus如何实现这种功能吧!

8. 乐观锁组件

这里的乐观锁和我们在前面学习的JUC中的乐观锁的概念相同,我们一块来回忆下什么是乐观锁和悲观锁:

  • 乐观锁:通常认为不会出现并发问题,不会去真正的加锁。当出现问题时,就更新值重新测试。
  • 悲观锁:通常总是认为可能出现问题,因此在进行任何操作时都进行加锁再去操作。

那么,MyBaits-Plus提供的乐观锁又是怎么实现的呢?我们又该如何编写代码使用呢?一起来学习下吧!

MyBatis-Plus提供的乐观锁的实现原理:

  1. 数据库表中要有一个版本号字段version;
  2. 取出数据时会带上这个version信息;
  3. 执行更新操作时会判断当前的version和之前获取的旧版本的version是否相同;
  4. 前后查询到的version相同就更新并修改版本号,否则更新失败。

通过上述的这些步骤,就可以避免并发环境下更新数据带来的覆盖问题。


MyBatis-Plus乐观锁的代码实现:

了解了乐观锁的实现原理,我们得现在数据库表中新增一个version字段信息:

接下来我们就来编写代码实现这一功能:

  

9. 分页查询组件

在之前的项目中,我们往往是通过接口前端传递的参数并计算然后结合数据库关键字limit来实现分页功能的,学习了MyBatis-Plus之后,就不用这么麻烦了!它为我们提供了一个非常好用的分页查询组件,在查询的时候只需要传入页码和每页的数据条数就可以了,大大提高了我们开发的效率!接下来一起来感受下组件分页带来的便利吧!

实现MyBatis-Plus的分页查询:

10. 性能分析组件

 MyBatis-Plus也为我们提供了SQL执行的性能分析组件,比如我们可以通过配置该组件在开发或者测试的过程中来检测SQL的执行时间并做出优化等处理。接下来来记录下早Mybatis

-Plus中该如何注册并使用这个组件:

11. wrapper条件查询器

在上面我们的学习过程中,已经提到了wrapper条件构造器,它主要用来构造执行的SQL语句中的负责查询条件,这些条件又是通过map条件查询很难实现的,同时也通过api的调用更加简化了我们编写SQL语句的步骤,提高了开发效率。接下来一起来学习下wrapper构造器构造简单查询条件的实现,具体的使用可以参照:Mybatis-Plus官方文档


package com.shuai.mybatis_plus;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shuai.mybatis_plus.entity.User;
import com.shuai.mybatis_plus.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;
import java.util.Map;

@SpringBootTest
public class WrapperTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void wrapperTest1() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.select("id", "name");
        /**
         * 设置只查询user表中的id,name字段
         * 执行的SQL:
         *     SELECT
         *         id,
         *         name
         *     FROM
         *         user
         *     WHERE
         *         deleted=0
         */
        userMapper.selectList(userQueryWrapper).forEach(System.out::println);
    }

    @Test
    public void wrapperTest2() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper
                .eq("name", "白小帅")
                .ge("id", 6);
        /**
         * 查询 name=白小帅 并且 id>=6 的用户信息
         * 执行的SQL:
         * SELECT
         *         id,
         *         name,
         *         age,
         *         email,
         *         version,
         *         create_time,
         *         update_time
         *     FROM
         *         user
         *     WHERE
         *         deleted=0
         *         AND name = '白小帅'
         *         AND id >= 6
         */
        List<User> users = userMapper.selectList(userQueryWrapper);
        users.forEach(System.out::println);
    }

    @Test
    public void wrapperTest3() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper
                .gt("age", 16)
                .likeLeft("email", ".com");
        /**
         * 查询年龄大于16,并且模糊匹配email字段为 .com%
         * 执行的SQL:
         * SELECT
         *         COUNT( 1 )
         *     FROM
         *         user
         *     WHERE
         *         deleted=0
         *         AND age > 16
         *         AND email LIKE '%.com'
         */
        Integer count = userMapper.selectCount(userQueryWrapper);
        System.out.println(count);
    }

    @Test
    public void wrapperTest4() {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper
                .between("age", "18", "28")
                .select("id", "name", "age")
                .in("id", 2, 3, 4)
                .orderByDesc("age");
        /**
         * 查询年龄在18-28之间的用户,包含字段 id,name和 age 并且 id在2,3,4的用户信息,并降序排序
         * 执行的SQL:
         * SELECT
         *         id,
         *         name,
         *         age 
         *     FROM
         *         user 
         *     WHERE
         *         deleted=0 
         *         AND age BETWEEN '18' AND '28' 
         *         AND id IN (
         *             2,3,4
         *         ) 
         *     ORDER BY
         *         age DESC
         */
        List<Map<String, Object>> userMaps = userMapper.selectMaps(userQueryWrapper);
        userMaps.forEach(System.out::println);
    }
}

ps:

在使用时注意wrapper对象的likeLeft和likeRight方法,likeLeft相当于模糊匹配的 ‘%’ 在左侧,likeRight相当于模糊匹配的 ‘%’在右侧,例如:

  • userQueryWrapper.likeLeft('abc') 对应 SQL中模糊匹配 like '%abc'
  • userQueryWrapper.likeRight('abc') 对应 SQL中模糊匹配 like 'abc%'
  • userQueryWrapper.like('abc') 对应 SQL中模糊匹配 like '%abc%'

12. 代码自动生成器

前面学习到的Mybatis-Plus组件可以说是开胃菜,而这个代码自动生成器可以说是重头戏,学完这个组件你将会止不住惊叹。它能够为我们自动生成后端架构的Controller、Service乃至Entity和Mapper层的所有基础代码,快来一块学习下吧!

        


package com.shuai.mybatis_plus;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.util.ArrayList;
import java.util.Scanner;

public class CodeGeneratorAuto {
    private static final String URL = "jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "BXS552ZXY";
    private static final DbType DBTYPE = DbType.MYSQL;
    //自动生成代码的父目录
    private static final String PACKAGE_PARENT_CONFIG = "com.shuai.mybatis_plus";
    //设置逻辑删除字段名
    private static final String LOGIC_FIELD_NAME = "deleted";
    //设置乐观锁字段名
    private static final String VERSION_FIELD_NAME = "version";
    //设置自动填充属性名
    private static final String AUTO_FILL_FIELD1 = "gmt_create";  //自动填充属性1
    private static final FieldFill AUTO_FIELD1_FILL_STRATEGY = FieldFill.INSERT;    //属性1自动填充策略

    private static final String AUTO_FILL_FIELD2 = "gmt_modified";  //自动填充属性2
    private static final FieldFill AUTO_FIELD2_FILL_STRATEGY = FieldFill.INSERT_UPDATE;    //属性2自动填充策略
    private static final String DB_DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";

    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }

    public static void main(String[] args) {
        //创建代码生成器对象
        AutoGenerator mpg = new AutoGenerator();

        //全局配置
        GlobalConfig gc = new GlobalConfig();   //不要导错包了:com.baomidou.mybatisplus.generator.AutoGenerator;
        String projectPath = System.getProperty("user.dir");    //获取项目路径
        gc.setOutputDir(projectPath + "/src/main/java");  //设置自动生成代码的输出路径
        gc.setAuthor(scanner("作者名"));   //设置作者信息
        gc.setOpen(false);                  //生成代码时不用打开文件资源管理器
        gc.setFileOverride(false); // 是否覆盖
        gc.setServiceName("%sService"); // 去Service的I前缀
        gc.setIdType(IdType.ID_WORKER); //设置主键生成策略为自增
        gc.setDateType(DateType.ONLY_DATE); //设置时间格式为Date
        mpg.setGlobalConfig(gc);

        //数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(URL);
        dsc.setUsername(USERNAME);
        dsc.setPassword(PASSWORD);
        dsc.setDriverName(DB_DRIVER_CLASS_NAME);
        dsc.setDbType(DBTYPE);
        mpg.setDataSource(dsc);

        //包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(scanner("模块名"));
        pc.setParent(PACKAGE_PARENT_CONFIG);
        //设置每一层的包名
        pc.setController("controller");
        pc.setService("service");
        pc.setMapper("mapper");
        pc.setEntity("entity");
        mpg.setPackageInfo(pc);


        //策略配置
        StrategyConfig sc = new StrategyConfig();
        sc.setNaming(NamingStrategy.underline_to_camel);    //设置数据库表名映射到实体属性的命名策略为下划线转驼峰
        sc.setColumnNaming(NamingStrategy.underline_to_camel);  //设置数据库字段映射到实体属性的命名策略为下划线转驼峰,未指定按照naming执行
        sc.setEntityLombokModel(true);          //【实体】是否为lombok模型(默认 false)
        sc.setRestControllerStyle(true);        //生成 @RestController 控制器   @Controller -> @RestController
        sc.setInclude(scanner("表名,多个英文逗号分割").split(","));
        sc.setLogicDeleteFieldName(LOGIC_FIELD_NAME);   //设置逻辑删除属性名
        // 自动填充配置
        TableFill gmtCreate = new TableFill(AUTO_FILL_FIELD1, AUTO_FIELD1_FILL_STRATEGY);
        TableFill gmtModified = new TableFill(AUTO_FILL_FIELD2, AUTO_FIELD2_FILL_STRATEGY);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(gmtCreate);
        tableFills.add(gmtModified);
        sc.setTableFillList(tableFills);
        sc.setVersionFieldName(VERSION_FIELD_NAME);  //设置乐观锁字段名
        sc.setControllerMappingHyphenStyle(true); //localhost:8080/hello_id_2
        mpg.setStrategy(sc);
        mpg.execute(); //执行
    }
}

 

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

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

相关文章

Nacos报错Could not resolve placeholder ‘order.name‘ in value “${order.name}“怎么解决?

出现这个原因有两个&#xff1a; 1.首先在Nacos配置中心&#xff0c;写入yml配置文件的数据和后端服务在取数据的时候名称不一致 如下图&#xff0c;现在我的配置中心为order-service 看看其中的文件内容信息&#xff1a; 再看看后端是怎么取的&#xff1a; 看出上面错误了吗…

Windows Cluster 投票权问题

在日常运维中&#xff0c;如果你的 Windows Cluster 需要升级、重启、意外宕机、网络中断等&#xff0c;你知道该怎么操作才能保证集群的可用性吗&#xff1f;按什么样的顺序怎样关闭或启动集群节点吗&#xff1f;怎么快速恢复你的集群呢&#xff1f; 接下来&#xff0c;我们就…

【C++ 重要知识点总结】STL字符串向量

字符串、向量和数组 这里讲的是 C中的处理&#xff0c;置于 C 中的字符串向量和数组&#xff0c;可以自己去复习。 1 命名空间的 using 声明 基本使用 //独立使用名字 using namespace::name; //声明空间 using namespace使用规则 头文件中不应包含 using 声明。因为会破坏包…

组合数学相关知识总结(适合复习用)

全排列 例子&#xff1a; n n n 个数取 m m m 个数有序排放 通项公式&#xff1a; A n m ( P n m ) n ∗ ( n − 1 ) ∗ ( n − 2 ) ∗ ⋅ ⋅ ⋅ ∗ ( n − m 1 ) n ! ( n − m ) ! A_n^m(P_n^m)n*(n-1)*(n-2)**(n-m1) \frac{n!}{(n-m)!} Anm​(Pnm​)n∗(n−1)∗(n−2)∗…

[QT编程系列-12]:QT快速学习 - 0 - 主要内容

第0章 主要内容 0.1 QT的主要内容 附录&#xff1a; Qt 是一个功能强大的应用程序开发框架&#xff0c;涵盖了广泛的知识点。以下是一些常见的 Qt 知识点&#xff1a; 基本概念和特性&#xff1a;了解 Qt 的基本概念&#xff0c;如信号和槽、事件处理、对象模型、元对象系统等…

Python基础合集 练习27 (turtle函数使用)

import turtle as t 画笔控制工具 t.penup() 表示画笔抬起 海龟在天上飞 不能直接形成图形 t.pendown() 画笔落下 海龟降下来 t.pensize(15) 也可以用 t.width() 画笔宽度 t.pencolor(“red”) 画笔颜色 为颜色字符串或rgb值 运动控制函数 控制行进方向、走曲线或…

二进制文件的Python写入

二进制文件的Python编写 这么基础的东西&#xff0c;必然用内置的就好 二进制文件的Python读写 重要提示 p.s. 1 >>> bHello World.decode() "Hello World" True >>> example import struct with open(binary_file.bin, wb) as file:data b…

【cfengDB】自己实现数据库第0节 ---整体介绍及事务管理层实现

LearnProj 内容管理 MySQL系统结构一条SQL执行流程 cfengDB整体结构事务管理TM模块TID文件规则定义文件读写 -- NIORandomAccessFile、FileChannel、ByteBuffer接口实现文件合法检测begin()commit(tid)rollback(tid)tid文件创建 本文作为数工底层的项目CfengDB开始篇章&#xf…

vue 升级3 +vite+antdv4

目录 一、安装包相关升级 二、vite.config 三、 入口文件修改 四、App.vue 及相关升级 五、路由 六、状态管理VUEX 一、安装包相关升级 升级pakage.json相关安装包 vue2插件vue3替换插件vue2使用vue3使用vue-ls vuex-persistedstate或vuex-persistVue.ls.get() Vue.ls.…

C++ 多线程学习总结

C 多线程 创建线程 thread jion与detach方式的区别 jion方式&#xff1a;必须等待创建并启动的子线程任务执行完毕&#xff0c;才会继续往下执行。 示例&#xff1a; #include <stdio.h> #include <unistd.h> #include <iostream> #include <string&g…

【企业架构实践】要避免的 7 个企业架构错误

颠覆性时代需要有弹性、前瞻性的企业架构。不要让错误的框架破坏您的组织实现当前和未来目标的能力。 企业架构为成功的业务 IT 计划奠定了基础。如果设计和实施得当&#xff0c;企业架构将帮助业务领导者实现他们的目标&#xff0c;使组织变得更具响应性、效率和竞争力。 不幸…

matlab使用教程(2)—数组索引、工作区与字符

1数组索引 MATLAB 中的每个变量都是一个可包含许多数字的数组。如果要访问数组的选定元素&#xff0c;请使用索引。 例如&#xff0c;假设有 44 矩阵 A &#xff1a; A [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16] A 44 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 引…

python selenium.webdriver 爬取政策文件

文章目录 获取文章链接批量爬取政策文件应用selenium爬取文件信息数据处理导出为excel 获取文章链接 获取中央人民政府网站链接&#xff0c;进入国务院政策文件库&#xff0c;分为国务院文件和部门文件&#xff08;发改委、工信部、交通运输部、市场监督局、商务部等&#xff…

JavaScript 中 五种迭代数组的方法 every some map filter forEach

JavaScript 中 五种迭代数组的方法 every some map filter forEach 1.every 和 some2.filter (重点常用)3.map (灵活常用&#xff09;4.forEach (重点常用) ECMAScript 提供了 5个对数组的迭代方法 1.every() 2.some() 3.filter() 4.forEach() 5.map() 1.every 和 some every…

串联型PI和并联型PI调节器的比较

一、PI调节器的种类 图3-4 仿真波形变化情况&#xff08;串联型PI调节器&#xff0c;1500r/min&#xff09; 从图3-1到3-4比较可知&#xff0c;与并联型PI调节器相比&#xff0c;串联型PI调节器的超调量很小&#xff08;速度环&#xff09;&#xff0c;且动态过程时间短&…

从新的角度看待大模型微调

一、前言 一切要从最近大火的Lora(《LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS》&#xff09;说起&#xff0c;该文章在ICLR2022中提出。说的是利用低秩适配(low-rank adaptation)的方法&#xff0c;可以在使用大模型适配下游任务时只需要训练少量的参数即可达到一…

【SQL应知应会】表分区(二)• MySQL版

欢迎来到爱书不爱输的程序猿的博客, 本博客致力于知识分享&#xff0c;与更多的人进行学习交流 本文收录于SQL应知应会专栏,本专栏主要用于记录对于数据库的一些学习&#xff0c;有基础也有进阶&#xff0c;有MySQL也有Oracle 分区表 • MySQL版 前言一、分区表1.非分区表2.分区…

【运维】第03讲(下):Nginx 负载均衡常见架构及问题解析

Nginx 负载均衡常见问题 那么,Nginx 负载均衡的通常配置会出现哪些问题呢?这里列出几种比较常见的问题: 客户端 IP 地址获取问题域名携带问题负载均衡导致 session 丢失问题动态负载均衡问题真实的 Realserver 状态检测接下来,我们就重点讲解下 Nginx 作为负载均衡的这几个…

从代码角度戳一下springMVC的运行过程-spring16

1、首先页面需要输入地址&#xff1a; 2、画张图------ 这个地址先找Tomcat,而Tomcat帮你找你的工程 3、 4、每次都要过这个地方 这句servlet代码 具体流程是&#xff1a; SpringMVC的执行流程 这个Handler干嘛&#xff1f;负责对你的请求进行解析&#xff0c;知道我最终要找…

WAIC2023丨AI图像内容安全“黑科技”如何助力科技发展?

〇、前言 7月7日下午&#xff0c;2023世界人工智能大会&#xff08;WAIC&#xff09;“聚焦大模型时代AIGC新浪潮—可信AI”论坛在上海世博中心红厅举行。人工智能等技术前沿领域的著名专家与学者、投资人和领军创业者汇聚一堂&#xff0c;共同探索中国科技创新的驱动力量。 在…