【MyBatis Plus】使用 MyBatis Plus 完成分页功能,以及通用分页实体的实现

news2025/2/25 9:10:19

文章目录

  • 一、MyBatis Plus 分页插件
    • 1.1 了解 MyBatis Plus 的插件功能
    • 1.2 配置分页插件
    • 1.3 测试分页功能
  • 二、实现通用分页实体
    • 2.1 分页查询需求
    • 2.2 分页实体类
    • 2.3 分页查询接口
    • 2.4 通用实体的转换
      • 2.4.1 PageQuery 转换为 MP Page
      • 2.4.2 分页结果 PO 转换 VO


一、MyBatis Plus 分页插件

1.1 了解 MyBatis Plus 的插件功能

当使用 MyBatis Plus 的插件功能时,可以通过配置不同的插件来满足项目的需求。这些插件可以增强 MyBatis Plus 的功能,提高数据库操作的效率和安全性。以下是对主要插件的介绍:

插件功能
PaginationInnerInterceptor自动分页
TenantLineInnerInterceptor多租户
DynamicTableNameInnerInterceptor动态表名
OptimisticLockerInnerInterceptor乐观锁
IllegalSQLInnerInterceptorSQL 性能规范
BlockAttackInnerInterceptor防止全表更新与删除
  1. PaginationInnerInterceptor(自动分页)PaginationInnerInterceptor 用于实现自动分页功能。通过配置这个插件,可以轻松地在查询操作中启用分页,而无需手动编写分页查询的 SQL。插件会自动计算起始行和结束行,以获取指定范围的数据。

  2. TenantLineInnerInterceptor(多租户)TenantLineInnerInterceptor 插件用于支持多租户架构。在多租户环境中,不同租户共享同一数据库,但数据需要分隔。这个插件可以自动在 SQL 查询中添加租户条件,以确保每个租户只能访问自己的数据。

  3. DynamicTableNameInnerInterceptor(动态表名)DynamicTableNameInnerInterceptor 允许在运行时动态更改 SQL 查询中的表名。这对于根据不同的条件选择不同的表格非常有用,例如,可以根据用户身份或其他因素选择不同的表格。

  4. OptimisticLockerInnerInterceptor(乐观锁)OptimisticLockerInnerInterceptor 用于支持乐观锁机制。乐观锁是一种并发控制方式,可以防止多个用户同时修改同一记录。这个插件会自动为实体添加乐观锁的版本字段,并在更新操作中检查版本号,以确保数据的一致性。

  5. IllegalSQLInnerInterceptor(SQL 性能规范)IllegalSQLInnerInterceptor 用于检查 SQL 查询语句的性能规范。它可以帮助开发者优化 SQL 查询,减少潜在的性能问题。通过检查 SQL 的性能规范,可以提高查询的效率。

  6. BlockAttackInnerInterceptor(防止全表更新与删除)BlockAttackInnerInterceptor 用于防止执行全表更新和删除操作。这有助于减少潜在的危险操作,以保护数据库的安全性。插件可以拦截包含特定条件的 SQL 查询,阻止执行这些操作。

通过合理配置这些插件,可以提高 MyBatis Plus 的功能和性能,以满足不同项目的需求,并且这些插件使数据库操作更加高效和安全。下面将演示如何利用 PaginationInnerInterceptor 自动分页插件来实现分页功能。

1.2 配置分页插件

在没有引入分页插件的情况下,Mybatis Plus 是不支持分页功能的,IServiceBaseMapper 中的分页方法都无法正常生效。所以,我们必须配置分页插件,简单来说,就是创建一个配置类,然后注册一个 Bean 对象:

@Configuration
public class MyBatisConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        
        // 初始化 MybatisPlusInterceptor 核心插件
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加自动分页插件 PaginationInnerInterceptor
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        // 返回
        return interceptor;
    }
}

对上面代码的说明:

  1. 创建一个 Java 配置类 MyBatisConfig 并使用 @Configuration 注解标记它,这将使它成为一个 Spring Boot 的配置类。

  2. 通过 @Bean 注解,创建了一个名为 mybatisPlusInterceptorBean 对象,这个 Bean 是 Mybatis Plus 核心插件 MybatisPlusInterceptor 的实例。

  3. mybatisPlusInterceptor 的 Bean 中,初始化 MybatisPlusInterceptor 的核心插件,并将分页插件 PaginationInnerInterceptor 添加到其中。

  4. 通过 interceptor.addInnerInterceptor(new PaginationInnerInterceptor()) 语句,将分页插件添加到核心拦截器中,从而启用了分页功能。

通过这样的配置,MyBatis Plus 将能够正常支持分页功能,IServiceBaseMapper 中的分页方法将生效。当执行带有分页参数的查询时,分页插件将自动计算起始行和结束行,并修改 SQL 查询语句,以获取指定范围的数据。

1.3 测试分页功能

下面编写一个分页查询的测试类,查询第一页的数据,每一页最多两条记录:

@Test
void testPageQuery() {
    // 1. 准备分页查询条件
    Page<User> page = new Page<>();
    // 1.1.设置分页参数
    page.setCurrent(0).setSize(2);
    // 2. 分页查询,最终返回的结果保存在 page 对象中
    page = userService.page(new Page<>(0, 2));
    // 3. 总条数
    long total = page.getTotal();
    // 4. 总页数
    long pages = page.getPages();

    System.out.println("总条数:" + total + " 总页数:" + pages);
    // 5. 当前页数据
    List<User> users = page.getRecords();
    users.forEach(System.out::println);
}

对上面测试代码的解释:

  1. testPageQuery 方法中,首先准备了一个分页查询条件。这是通过创建一个 Page<User> 对象来实现的,其中 User 是要查询数据库表的实体类。

  2. 在分页查询条件中,设置了分页参数,包括当前页和每页记录数。在示例中,当前页为 0(第一页),每页最多显示 2 条记录。

  3. 接下来,使用 userService.page(new Page<>(0, 2)) 执行分页查询。page() 方法是 MyBatis Plus 提供的分页查询方法。查询结果将存储在 page 对象中。

  4. 通过 page.getTotal() 获取总记录数,这是符合查询条件的所有记录数量。

  5. 通过 page.getPages() 获取总页数,这是根据分页参数计算得出的。

  6. 最后,通过 page.getRecords() 获取当前页的数据列表,并通过 forEach 方法遍历打印每条记录。

这个测试代码用于验证分页功能是否正常工作,以及是否返回了正确的分页结果。

最终运行结果:


另外,这里用到的分页参数Page,既可以支持分页参数,也可以支持排序参数。例如按照 balance 进行降序排序:

// 1. 准备分页查询条件
Page<User> page = new Page<>();
// 1.1.设置分页参数
page.setCurrent(0).setSize(2);
// 1.2.设置排序规则
page.addOrder(new OrderItem("balance", false));

其中OrderItem类就是用于设置排序规则,第一个参数用于指定排序的字段,第二个参数则指定是否是升序排序,设置 false 则为降序。

二、实现通用分页实体

2.1 分页查询需求

现在要实现一个用户分页查询的接口,接口规范如下:

  1. 请求方式:GET

  2. 请求路径:/users/page

  3. 请求参数:

    {
        "pageNo": 1,
        "pageSize": 5,
        "sortBy": "balance",
        "isAsc": false,
        "name": "o",
        "status": 1
    }
    
  4. 响应数据格式:

    {
        "total": 100006,
        "pages": 50003,
        "list": [
            {
                "id": 1685100878975279298,
                "username": "user_9****",
                "info": {
                    "age": 24,
                    "intro": "英文老师",
                    "gender": "female"
                },
                "status": "正常",
                "balance": 2000
            }
        ]
    }
    
  5. 特殊说明:

    • 如果排序字段为空,默认按照更新时间排序;
    • 排序字段不为空,则按照排序字段排序。

要实现上面这个接口,首先需要定义 3 个实体类:

  • UserQuery:分页查询条件的实体,包含分页、排序参数、过滤条件
  • PageDTO:分页结果实体,包含总条数、总页数、当前页数据
  • UserVO:用户页面视图实体

2.2 分页实体类

  1. UserQuery 之前已经定义过了,并且其中已经包含了过滤条件,具体代码如下:

    @Data
    @ApiModel(description = "用户查询条件实体")
    public class UserQuery {
        @ApiModelProperty("用户名关键字")
        private String name;
        @ApiModelProperty("用户状态:1-正常,2-冻结")
        private Integer status;
        @ApiModelProperty("余额最小值")
        private Integer minBalance;
        @ApiModelProperty("余额最大值")
        private Integer maxBalance;
    }
    
  2. 其中缺少的仅仅是分页条件,而分页条件不仅仅用户分页查询需要,以后其它业务也都有分页查询的需求。因此最好将分页查询条件单独定义为一个PageQuery实体。

    PageQuery是前端提交的分页查询参数,一般包含以下四个属性:

    • pageNo:页码
    • pageSize:页面大小
    • sortBy:排序字段
    • isAsc:是否升序

    下面是 PageQuery 实体类的实现代码:

    @Data
    @ApiModel(description = "分页查询实体类")
    public class PageQuery {
        @ApiModelProperty("页码")
        private Integer pageNo;
        @ApiModelProperty("页面大小")
        private Integer pageSize;
        @ApiModelProperty("排序字段")
        private String sortBy;
        @ApiModelProperty("是否升序")
        private Boolean isAsc;
    }
    
  3. 然后,让 UserQuery 继承这个实体:
    这里使用了 Lombok 提供的注解 @EqualsAndHashCode 来重写 equalshashCode 方法。

  4. 这里返回值的用户实体沿用之前实现的一个 UserVO 实体:

  5. 最后,我们需要实现PageDTO实体,用于返回分页查询的结果,由于后面可能会针对多张表进行分页查询,因此这里将其实现为泛型类,具体的实现代码如下:

    @Data
    @ApiModel("分页结果实体")
    public class PageDTO<T> {
        @ApiModelProperty("总条数")
        private Long total;
        @ApiModelProperty("总页数")
        private Long pages;
        @ApiModelProperty("当前页数据集合")
        private List<T> list;
    }
    

2.3 分页查询接口

当完成了上述所有实体类的准备之后,就可以定义分页查询的接口了。

  1. 首先使用 Controller 方法,在 UserController 中新增一个 queryUsersPage 接口:

    @Api(tags = "用户管理接口")
    @RequestMapping("/user")
    @RestController
    public class UserController {
        @Autowired
        private IUserService userService;
    		
    		// ...
    		
        @GetMapping("/page")
        @ApiOperation("根据复杂条件分页查询用户接口")
        public PageDTO<UserVO> queryUsersPage(UserQuery query){
            return userService.queryUsersPage(query);
        }
    }
    
  2. 实现 Service 接口

    • 首先在 IUserService 中定义 queryUsersPage 方法
    
    public interface IUserService extends IService<User> {
    		// ...
        PageDTO<UserVO> queryUsersPage(UserQuery query);
    }
    
    
    • 然后在 UserServiceImpl 中实现 queryUsersPage 方法
    @Override
    public PageDTO<UserVO> queryUsersPage(UserQuery query) {
        // 1. 准备分页查询条件
        // 1.1.分页条件
        Page<User> page = Page.of(query.getPageNo(), query.getPageSize());
        // 1.2.排序条件
        if(query.getSortBy().isEmpty()){
            // 如果排序字段为空,按照更新时间排序
            page.addOrder(new OrderItem("update_time", false));
        } else {
            page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));
        }
        // 2. 查询,查询的接口将封装到 page 对象中。
        this.page(page);
        // 3. 数据非空校验
        List<User> users = page.getRecords();
        if(users == null || users.isEmpty()){
            return new PageDTO<>(page.getTotal(), page.getPages(), Collections.emptyList());
        }
        // 4. 存在数据,进行实体类转换
        List<UserVO> list = BeanUtil.copyToList(users, UserVO.class);
    
        // 5. 封装返回结果
        return new PageDTO<>(page.getTotal(), page.getPages(), list);
    }
    

完成上述代码之后,发送如下请求:
返回结果:

虽然通过上面的操作之后,实现了通用分页实体,但是我们发现在实现的queryUsersPage方法中有很大篇幅的代码,像其中的准备分页条件、最终结果的转换等等基本都是通用的代码,如果要实现其他表的分页查询功能的时候,这些代码就又需要再写一遍。因此我们可以考虑将这一部分代码封装起来。

2.4 通用实体的转换

2.4.1 PageQuery 转换为 MP Page

让我们首先来改造准备分页条件的代码,在刚才的代码中,从 PageQuery 到 Mybatis Plus的 Page 之间转换的过程还是比较麻烦的。因此我们可以直接将这段代码封装到 PageQuery 实体中,作为一个工具方法来简化开发。

例如:

@ApiModel(description = "分页查询实体类")
public class PageQuery {
    @ApiModelProperty("页码")
    private Integer pageNo;
    @ApiModelProperty("页面大小")
    private Integer pageSize;
    @ApiModelProperty("排序字段")
    private String sortBy;
    @ApiModelProperty("是否升序")
    private Boolean isAsc;


    /**
     * 将 PageQuery 转化为 Mybatis Plus Page
     *
     * @param orderItems 手动设置排序条件
     * @param <T>        泛型
     * @return Mybatis Plus Page
     */
    public <T> Page<T> toMpPage(OrderItem... orderItems) {
        // 1. 分页条件
        Page<T> p = Page.of(pageNo, pageSize);
        // 2. 排序提交
        if (sortBy != null) {
            p.addOrder(new OrderItem(sortBy, isAsc));
            return p;
        }

        if (orderItems != null) {
            p.addOrder(orderItems);
        }
        return p;
    }

    // 手动传入排序方式
    public <T> Page<T> toMpPage(String defaultSortBy, boolean isAsc) {
        return this.toMpPage(new OrderItem(defaultSortBy, isAsc));
    }

    // 默认 按照 CreateTime 降序排序
    public <T> Page<T> toMpPageDefaultSortByCreateTimeDesc() {
        return this.toMpPage("create_time", false);
    }

    // 默认 按照 UpdateTime 降序排序
    public <T> Page<T> toMpPageDefaultSortByUpdateTimeDesc() {
        return this.toMpPage("update_time", false);
    }
}

这样我们在编写 Service 代码的时候就可以省去对从 PageQueryPage 的转换了:

// 1.构建条件
Page<User> page = query.toMpPageDefaultSortByCreateTimeDesc();

2.4.2 分页结果 PO 转换 VO

在查询出分页结果后,数据的非空校验,数据的 VO 转换同样都是模板代码,编写起来很麻烦。因此我们同样可以将其封装到 PageDTO 的工具方法中,简化整个过程:

@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel("分页结果实体")
public class PageDTO<T> {
    @ApiModelProperty("总条数")
    private Long total;
    @ApiModelProperty("总页数")
    private Long pages;
    @ApiModelProperty("当前页数据集合")
    private List<T> list;


    /**
     * 返回空的分页结果
     * @param p MyBatis Plus 的分页结果
     * @param <V> 目标 VO 类型
     * @param <P> 原始的 PO 类型
     * @return VO 的分页结果
     */
    public static <V, P> PageDTO<V> empty(Page<P> p) {
        return new PageDTO<>(p.getTotal(), p.getPages(), Collections.emptyList());
    }

    /**
     * 将 MyBatis Plus 的分页结果转换为 VO 的分页结果
     * @param p MyBatis Plus 的分页结果
     * @param voClass 目标 VO 类型的字节码
     * @param <V> 目标 VO 类型
     * @param <P> 原始的 PO 类型
     * @return VO 的分页结果
     */
    public static <V, P>PageDTO<V> of(Page<P> p, Class<V> voClass){
        // 1. 非空校验
        List<P> records = p.getRecords();
        if(records == null || records.isEmpty()){
            // 无数据,返回空结果
            return empty(p);
        }
        // 2. 数据转换
        List<V> vos = BeanUtil.copyToList(records, voClass);
        // 3. 封装返回
        return new PageDTO<>(p.getTotal(), p.getPages(), vos);
    }


    /**
     * 将 Mybatis Plus分页结果转为 VO分页结果,允许用户自定义 PO到 VO的转换方式
     * @param p Mybatis Plus的分页结果
     * @param convertor PO 到 VO的转换函数
     * @param <V> 目标 VO 类型
     * @param <P> 原始 PO 类型
     * @return VO 的分页结果
     */
    public static <V, P>PageDTO<V> of(Page<P> p, Function<P, V> convertor){
        // 1. 非空校验
        List<P> records = p.getRecords();
        if(records == null || records.isEmpty()){
            // 无数据,返回空结果
            return empty(p);
        }
        // 2. 数据转换
        List<V> vos = records.stream().map(convertor).collect(Collectors.toList());
        // 3. 封装返回
        return new PageDTO<>(p.getTotal(), p.getPages(), vos);
    }
}

完成了上面所有的功能之后,最后 queryUsersPage 的实现方法就变成了:

@Override
public PageDTO<UserVO> queryUsersPage(UserQuery query) {
    // 1. 准备分页条件
    Page<User> p = query.toMpPageDefaultSortByCreateTimeDesc();
    // 2. 分页查询
    this.page(p);
    // 3. 封装返回
    return PageDTO.of(p, UserVO.class);
}

此时,三行代码就完成了,并且如果要对其他数据库表进行分页查询,也通用能够复用这些代码。

另外,如果是希望自定义 PO 到 VO 的转换过程,可以这样做:

@Override
public PageDTO<UserVO> queryUsersPage(UserQuery query) {
    // 1. 准备分页条件
    Page<User> p = query.toMpPageDefaultSortByCreateTimeDesc();
    // 2. 分页查询
    this.page(p);
    // 3. 封装返回
    return PageDTO.of(p, user -> {
        // 拷贝属性到 VO
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        // 用户名脱敏处理
        String username = userVO.getUsername();
        userVO.setUsername(username.substring(0, username.length() - 2) + "**");
        // 返回 userVO 对象
        return userVO;
    });
}

最终查询的返回结果:

发现成功对用户名实现了脱敏操作:

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

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

相关文章

canvas实现环形进度条

与setTimeout和setInterval不同&#xff0c;requestAnimationFrame不需要设置时间间隔。 效果图 源代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Canvas progress</title> </head&g…

GCC 编译器 详细总结

前言&#xff1a; 源文件需要经过编译才能生成可执行文件。 在 Windows 下进行开发时&#xff0c;只需要点几个按钮即可编译&#xff0c;集成开发环境(比如 Visual studio)已经将各种编译 工具的使用封装好了。 Linux 下也有很优秀的集成开发工具&#xff0c;但是更多的时候…

oracle如果不适用toad或者plsql工具如何获取索引建表语句

select dbms_lob.substr(dbms_metadata.get_ddl(INDEX,INDEX_NAME,DIXON))||; from dba_indexes where ownerDIXON这个语句可以获取dixon用户的所有索引创建语句&#xff0c;sql脚本形式呈现 点开一个语句查看 如果不使用dbms_lob.substr这个函数最后得到是一个clob selec…

基于Python+Django+Vue在线图书借阅网站、图书管理系统 - 毕业设计 - 课程设计

文章目录 源码下载地址项目介绍项目功能界面预览项目备注毕设定制&#xff0c;咨询 源码下载地址 点击这里下载代码 项目介绍 这是一个基于pythonvue开发的图书借阅网站。平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行…

牛客网刷题-(10)

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

Mongoose 开源库--SNTP 网络校时使用笔记

一、SNTP介绍 SNTP是一种简单的网络时间协议&#xff0c;它可以通过网络协议同步计算机的时间&#xff0c;时间的精度不如NTP。 关于SNTP介绍&#xff0c;可以参考 https://www.ionos.com/digitalguide/server/know-how/sntp-simple-network-time-protocol/ 或者 https://time…

docker部署Jenkins(Jenkins+Gitlab+Maven实现CI/CD)

GitLab介绍 GitLab是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务&#xff0c;可通过Web界面进行访问公开的或者私人项目。它拥有与Github类似的功能&#xff0c;能够浏览源代码&#xff0c;管理缺陷和注释。…

开发项目管理必备神器!10款好用的在线看板工具推荐!

在当今高速发展、竞争激烈的商业环境中&#xff0c;项目管理已经成为了许多组织的生存之道。项目管理可以有效地协调资源&#xff0c;监控进度&#xff0c;把握风险&#xff0c;并实现组织的策略目标。然而&#xff0c;传统的项目管理方法已经无法满足日益复杂和变化的工作需求…

框架安全-CVE 复现Apache ShiroApache Solr漏洞复现

文章目录 服务攻防-框架安全&CVE 复现&Apache Shiro&Apache Solr漏洞复现中间件列表常见开发框架Apache Shiro-组件框架安全暴露的安全问题漏洞复现Apache Shiro认证绕过漏洞&#xff08;CVE-2020-1957&#xff09;CVE-2020-11989验证绕过漏洞CVE_2016_4437 Shiro-…

JS动态转盘可手动设置份数与概率(详细介绍)

这个案例是我老师布置的一项作业&#xff0c;老师已详细讲解&#xff0c;本人分享给大家&#xff0c;详细为你们介绍如何实现。 我们转盘使用线段来实现 <!DOCTYPE html> <html> <head><meta charset"utf-8"><title></title>&l…

2023云栖大会:揭示未来科技的璀璨星辰

翻开科技世界的崭新篇章&#xff0c;2023年的云栖大会将在星光璀璨的杭州盛大开启。这一盛会&#xff0c;是科技创新的聚集地&#xff0c;也是前沿科技展示的殿堂。每年&#xff0c;无数优秀的科技人才和业内精英汇聚于此&#xff0c;共同探讨科技的未来趋势和人类发展的无限可…

编写shell脚本,利用mysqldump实现MySQL数据库分库分表备份

查看数据和数据表 mysql -uroot -p123456 -e show databases mysql -uroot -p123456 -e show tables from cb_d 删除头部Database和数据库自带的表 mysql -uroot -p123456 -e show databases -N | egrep -v "information_schema|mysql|performance_schema|sys"编写…

【Java 进阶篇】Java ServletContext详解:在Web应用中获取全局信息

在Java Web开发中&#xff0c;ServletContext是一个重要的概念&#xff0c;它允许我们在整个Web应用程序中共享信息和资源。本篇博客将深入探讨ServletContext的作用、如何获取它&#xff0c;以及如何在Web应用中使用它。无论您是刚刚入门的小白还是有一定经验的开发者&#xf…

QML WebEngineView 调用 JavaScript

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 在 QML 与 Web 混合开发时,除了使用 WebEngineView 加载网页之外,我们还可以在 QML 层运行 JavaScript 代码,这样就能更灵活地操作浏览器窗口和网页内容,从而实现丰富的交互功能了。例如:获取网页标题、…

【JavaEE初阶】 初识网络原理

文章目录 &#x1f332;网络发展史&#x1f6a9;独立模式&#x1f6a9;网络互连&#x1f4cc;局域网LAN&#x1f388;基于网线直连&#x1f388;基于集线器组建&#x1f388;基于交换机组建&#x1f388;基于交换机和路由器组建 &#x1f4cc;广域网WAN &#x1f340;网络通信基…

人工智能与脑机接口:开启人机融合的新时代

人工智能与脑机接口&#xff1a;开启人机融合的新时代 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;我们正与一个全新的时代相遇——人工智能与脑机接口相融合的时代。这个时代将带来前所未有的变革&#xff0c;让人类与机器的交互方式发生根本性的改变。…

洒洒水阿萨阿萨

1. 多表查询 多表查询(也叫关联查询, 联结查询): 可以用于检索涉及到多个表的数据. 使用关联查询, 可以将两张或多张表中的数据通过某种关系联系在一起, 从而生成需要的结果集.前提条件: 这些一起查询的表之间它们之间一定是有关联关系.# 先熟悉一下三张表: -- 1. 员工表(11个…

微信小程序快速备案的通道揭秘方法

随着国家政策的调整&#xff0c;微信小程序备案已变得刻不容缓。传统备案路径较为繁琐&#xff0c;耗时较长&#xff0c;为解决此痛点&#xff0c;今天我们将揭示一个快速备案的新通道。 步骤1&#xff1a;探索智慧助手 打开微信&#xff0c;探索“智慧商家服务助手”公众号。…

阿里云OS系统Alibaba Cloud Linux 3系统的安全更新命令

给客户部署的服务&#xff0c;进入运维阶段&#xff0c;但是经常被客户监测到服务器漏洞&#xff0c;现在整理一下&#xff0c;服务器漏洞问题更新命令步骤。 服务器系统&#xff1a; 阿里云linux服务器&#xff1a;Alibaba Cloud Linux 3 漏洞类型和描述&#xff1a; #3214…