MyBatisPlus——4 插件功能

4 插件功能

  • MybatisPlus提供了很多的插件功能,进一步拓展其功能。目前已有的插件有:

    • PaginationInnerInterceptor:自动分页
    • TenantLineInnerInterceptor:多租户
    • DynamicTableNameInnerInterceptor:动态表名
    • OptimisticLockerInnerInterceptor:乐观锁
    • IllegalSQLInnerInterceptor:sql 性能规范
    • BlockAttackInnerInterceptor:防止全表更新与删除
  • 注意: 使用多个分页插件的时候需要注意插件定义顺序,建议使用顺序如下:

    • 多租户,动态表名
    • 分页,乐观锁
    • sql 性能规范,防止全表更新与删除

4.1 分页插件

4.1.1 配置分页插件
  • 在项目中新建一个配置类:

    在这里插入图片描述

  • 其代码如下:

    package com.shisan.mp.config;
    
    import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MyBatisConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor(){
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            // 创建分页插件
            PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
            paginationInnerInterceptor.setMaxLimit(1000L); // 设置最大单页限制数量为1000条,默认 500 条,-1 不受限制
            // 添加分页插件
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
            return interceptor;
        }
    } 
    
4.1.2 分页API
  • 编写一个分页查询的测试:

    @Test
    void testPageQuery() {
        int pageNo = 1, pageSize = 2;
        //分页条件
        Page<User> page = Page.of(pageNo, pageSize);
        //排序条件
        page.addOrder(new OrderItem("balance", true));
        page.addOrder(new OrderItem("id", true));
        //分页查询
        Page<User> p = userService.page(page);
        //解析
        long total = p.getTotal();
        System.out.println("total = " + total);
        long pages = p.getPages();
        System.out.println("pages = " + pages);
        List<User> users = p.getRecords();
        users.forEach(System.out::println);
    }
    
  • 结果:

    在这里插入图片描述

4.2 通用分页实体

  • 需求:遵循下面的接口规范,编写一个UserController接口,实现User的分页查询;

    参数说明
    请求方式GET
    请求路径/users/page
    请求参数{
    “pageNo”: 1,
    “pageSize”: 5,
    “sortBy”: “balance”,
    “isAsc”: false,
    “name”: “o”,
    “status”: 1
    }
    返回值{
    “total”: 100006,
    “pages”: 50003,
    “list”: [
    {
    “id”: 1685100878975279298,
    “username”: “user_9****”,
    “info”: {
    “age”: 24,
    “intro”: “英文老师”,
    “gender”: “female”
    },
    “status”: “正常”,
    “balance”: 2000
    }
    ]
    }
    特殊说明如果排序字段为空,默认按照更新时间排序
    排序字段不为空,则按照排序字段排序
  • 这里需要定义3个实体:

    • UserQuery:分页查询条件的实体,包含分页、排序参数、过滤条件
    • PageDTO:分页结果实体,包含总条数、总页数、当前页数据
    • UserVO:用户页面视图实体
4.2.1 实体
  • UserQuery之前已经定义过了,并且其中已经包含了过滤条件,具体代码如下:

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

    在这里插入图片描述

    • PageQuery是前端提交的查询参数,一般包含四个属性:
      • pageNo:页码
      • pageSize:每页数据条数
      • sortBy:排序字段
      • isAsc:是否升序
    package com.shisan.mp.domain.query;
    
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    @Data
    @ApiModel(description = "分页查询实体")
    public class PageQuery {
        @ApiModelProperty("页码")
        private Long pageNo;
        @ApiModelProperty("页码")
        private Long pageSize;
        @ApiModelProperty("排序字段")
        private String sortBy;
        @ApiModelProperty("是否升序")
        private Boolean isAsc;
    }
    
    • 让UserQuery继承这个实体:

    在这里插入图片描述

  • 返回值的用户实体沿用之前定义的UserVO实体:

在这里插入图片描述

  • 分页实体PageDTO:

在这里插入图片描述

package com.shisan.mp.domain.dto;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

@Data
@ApiModel(description = "分页结果")
public class PageDTO<T> {
    @ApiModelProperty("总条数")
    private Long total;
    @ApiModelProperty("总页数")
    private Long pages;
    @ApiModelProperty("集合")
    private List<T> list;
}
4.2.2 开发接口
  • UserController中定义分页查询用户的接口:

    @ApiOperation("根据复杂条件分页查询用户接口")
    @GetMapping("/page")
    public PageDTO<UserVO> queryUsersPage(UserQuery query){
        return userService.queryUsersPage(query);
    }
    
  • IUserService中创建queryUsersPage方法:

    PageDTO<UserVO> queryUsersPage(UserQuery query);
    
  • UserServiceImpl中实现该方法

    @Override
    public PageDTO<UserVO> queryUsersPage(UserQuery query) {
        String name = query.getName();
        Integer status = query.getStatus();
        //1、构建条件
        //分页条件
        Page<User> page = Page.of(query.getPageNo(), query.getPageSize());
        //排序条件
        if(StrUtil.isNotBlank(query.getSortBy())){
            page.addOrder(new OrderItem(query.getSortBy(), query.getIsAsc()));
        }else{
            //为空,则按照更新时间排序
            page.addOrder(new OrderItem("update_time", false));
        }
    
        //2、分页查询
        Page<User> p = lambdaQuery()
                .like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, name)
                .page(page);
        //3、封装VO
        PageDTO<UserVO> dto = new PageDTO<>();
        //总条数
        dto.setTotal(p.getTotal());
        //总页数
        dto.setPages(p.getPages());
        //当前页数据
        List<User> records = p.getRecords();
        if(CollUtil.isEmpty(records)){
            dto.setList(Collections.emptyList());
            return dto;
        }
        List<UserVO> vos = BeanUtil.copyToList(records, UserVO.class);
        dto.setList(vos);
    
        //4、返回
        return dto;
    }
    
4.2.3 改造PageQuery实体和PageDTO实体
  • 在上节的代码中,从PageQueryMybatisPlusPage之间转换的过程还是比较麻烦的。可以在PageQuery这个实体中定义一个工具方法,将PageQuery对象转为MP中的Page对象,简化开发;

    package com.shisan.mp.domain.query;
    
    import cn.hutool.core.util.StrUtil;
    import com.baomidou.mybatisplus.core.metadata.OrderItem;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import com.shisan.mp.domain.po.User;
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    @Data
    @ApiModel(description = "分页查询实体")
    public class PageQuery {
        @ApiModelProperty("页码")
        private Long pageNo = 1L; //给默认值
        @ApiModelProperty("页码")
        private Long pageSize = 5L;
        @ApiModelProperty("排序字段")
        private String sortBy;
        @ApiModelProperty("是否升序")
        private Boolean isAsc = true;
    
        public <T> Page<T> toMpPage(OrderItem... orderItems) { //OrderItem用来存放业务层调用该方法时传递过来的默认排序条件
            //1、构建条件
            //分页条件
            Page<T> page = Page.of(pageNo, pageSize);
            //排序条件
            if (StrUtil.isNotBlank(sortBy)) { //若排序字段不为空
                page.addOrder(new OrderItem(sortBy, isAsc));
            } else if (orderItems != null) { //若排序字段为空,按照默认条件排序
                page.addOrder(orderItems);
            }
            return page;
        }
        public <T> Page<T> toMpPage(String defaultSortBy, Boolean defaultAsc) { //按照默认条件排序
            return toMpPage(new OrderItem(defaultSortBy, defaultAsc));
        }
        public <T> Page<T> toMpPageDefaultSortByCreateTime() { //默认按照创建时间倒序排序
            return toMpPage(new OrderItem("create_time", false));
        }
        public <T> Page<T> toMpPageDefaultSortByUpdateTime() { //默认按照修改时间倒序排序
            return toMpPage(new OrderItem("update_time", false));
        }
    }
    
  • 在查询出分页结果后,数据的非空校验,数据的vo转换都是模板代码,编写起来很麻烦。可以将其封装到PageDTO的工具方法中,在该方法中,将MP中的Page结果转为PageDTO结果。简化整个过程:

    package com.shisan.mp.domain.dto;
    
    import cn.hutool.core.collection.CollUtil;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    import java.util.Collections;
    import java.util.List;
    import java.util.function.Function;
    import java.util.stream.Collectors;
    
    @Data
    @ApiModel(description = "分页结果")
    public class PageDTO<T> {
        @ApiModelProperty("总条数")
        private Long total;
        @ApiModelProperty("总页数")
        private Long pages;
        @ApiModelProperty("集合")
        private List<T> list;
    
        public static <PO, VO> PageDTO<VO> of(Page<PO> p, Function<PO, VO> convertor){
            PageDTO<VO> dto = new PageDTO<>();
            //总条数
            dto.setTotal(p.getTotal());
            //总页数
            dto.setPages(p.getPages());
            //当前页数据
            List<PO> records = p.getRecords();
            if(CollUtil.isEmpty(records)){
                dto.setList(Collections.emptyList());
                return dto;
            }
            //拷贝user的VO
            dto.setList(records.stream().map(convertor).collect(Collectors.toList()));
    
            //返回
            return dto;
        }
    }
    
  • 修改UserServiceImpl.java中的代码:

    @Override
    public PageDTO<UserVO> queryUsersPage(UserQuery query) {
        String name = query.getName();
        Integer status = query.getStatus();
        //1、构建条件
        Page<User> page = query.toMpPageDefaultSortByUpdateTime();
    
        //2、分页查询
        Page<User> p = lambdaQuery()
                .like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, name)
                .page(page);
    
        return PageDTO.of(p, user -> {
            //1、拷贝基础属性
            UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
            //2、处理特殊逻辑
            vo.setUsername(vo.getUsername().substring(0, vo.getUsername().length() - 2) + "**");
            return vo;
        });
    }
    
### 关于 IntelliJ IDEA 中 MyBatisPlus 代码生成插件的使用和设置指南 #### 插件安装 为了在 IntelliJ IDEA 中配置并使用 MyBatisPlus 的代码生成功能,首先需要确保已安装相应的插件。可以通过访问官方插件市场来下载最新版本的支持包[^1]。 #### 配置数据库连接 MyBatisPlus 支持多种主流关系型数据库管理系统 (RDBMS),如 MySQL、PostgreSQL 和 Oracle 等。要使代码生成器正常工作,需先建立好与目标 RDBMS 的稳定连接。这通常涉及到编辑 `application.properties` 或者 `application.yml` 文件中的数据源属性配置项。 ```yaml spring: datasource: url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=UTC username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver ``` #### 设置实体类映射规则 通过定义全局配置文件内的特定参数,可以指定表名到实体类名称之间的转换逻辑以及字段命名策略等细节。这些设定有助于简化后续自动生成过程中的定制化需求处理。 ```java // GlobalConfig.java @Bean public GlobalConfig globalConfiguration() { GlobalConfig config = new GlobalConfig(); // 自定义输出路径,默认为 user.dir/src/main/java String projectPath = System.getProperty("user.dir"); config.setOutputDir(projectPath + "/src/main/java"); // 开启 XML 结果映射文件覆盖写入模式 config.setOpen(false); return config; } ``` #### 启动代码生成流程 完成上述准备工作之后,在IDEA内打开终端窗口执行命令行指令启动 MP Generator 工具;也可以利用图形界面操作方式触发该功能——即右键点击项目节点选择菜单选项 "Generate Code By MyBatis Plus" 来快速实现自动化脚本编写任务。 ```bash # Terminal Command Line Example mvn mybatis-Dmybatis.plus.generator.config-file=/path/to/generator-config.xml ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失散13

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值