深入 MyBatis-Plus 插件:解锁高级数据库功能

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。

一、关于Mybatis-Plus插件

1.1 简介

Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。

953921f3-2296-4535-9f98-4d4c3d801e2d

1.2 实现原理

Mybatis-Plus 的插件实现是基于 MyBatis 的拦截器机制, 这些插件通过 MybatisPlusInterceptor​ 来实现对 MyBatis 执行过程的拦截和增强。

MyBatis 插件本质上是对 SQL 执行过程的拦截和扩展,Mybatis-Plus 插件通过在 MyBatis 的执行生命周期中插入拦截器来实现一些增强功能。通过这种方式,Mybatis-Plus 可以实现分页、性能分析、乐观锁等功能的自动化处理。

MybatisPlusInterceptor 概览

MybatisPlusInterceptor​ 是 MyBatis-Plus 的核心插件,它代理了 MyBatis 的 Executor#query​、Executor#update​ 和 StatementHandler#prepare​ 方法,允许在这些方法执行前后插入自定义逻辑。

image

属性

MybatisPlusInterceptor​ 有一个关键属性 interceptors​,它是一个 List<InnerInterceptor>​ 类型的集合,用于存储所有要应用的内部拦截器。

InnerInterceptor 接口

所有 MyBatis-Plus 提供的插件都实现了 InnerInterceptor​ 接口,这个接口定义了插件的基本行为。目前,MyBatis-Plus 提供了以下插件:

  • 自动分页: PaginationInnerInterceptor
  • 多租户: TenantLineInnerInterceptor
  • 动态表名: DynamicTableNameInnerInterceptor
  • 乐观锁: OptimisticLockerInnerInterceptor
  • SQL 性能规范: IllegalSQLInnerInterceptor
  • 防止全表更新与删除: BlockAttackInnerInterceptor

1.3 配置方式

插件的配置可以在 Spring 配置中进行,也可以在 Spring Boot 项目中通过 Java 配置来添加。以下是两种配置方式的示例:

  • Spring 配置:在 Spring 配置中,需要创建 MybatisPlusInterceptor​ 的实例,并将它添加到 MyBatis 的插件列表中。
  • Spring Boot 配置:在 Spring Boot 项目中,可以通过 Java 配置来添加插件,例如添加分页插件。

Spring Boot 配置示例

@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {
   

    /**
     * 添加分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
   
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

配置多个插件

@Configuration
public class MyBatisPlusConfig {
   

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
   
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

        // 添加性能分析插件
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(1000); // 设置SQL最大执行时间,单位为毫秒
        interceptor.addInnerInterceptor(performanceInterceptor);

        // 添加防全表更新与删除插件
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());

        return interceptor;
    }
}

注意

使用多个插件时,需要注意它们的顺序。建议的顺序是:

  1. 多租户、动态表名
  2. 分页、乐观锁
  3. SQL 性能规范、防止全表更新与删除

总结:对 SQL 进行单次改造的插件应优先放入,不对 SQL 进行改造的插件最后放入。

二、分页插件(PaginationInnerInterceptor​)

2.1 关于

简介

MyBatis-Plus 的分页插件 PaginationInnerInterceptor​ 提供了强大的分页功能,支持多种数据库,使得分页查询变得简单高效。用时只需要在查询方法中传入Page<T>​对象,插件会自动处理分页相关的SQL构建和结果集解析。

image

主要功能

  1. 自动分页

    • 通过在查询时自动添加 LIMIT​ 和 OFFSET​ 等 SQL 关键字,来实现分页功能。
  2. 兼容性

    • 支持多种数据库的分页语法,确保在不同数据库上都能正常工作。
  3. 动态参数

    • 可以动态地根据用户的请求参数(如页码和每页大小)生成分页信息,而无需手动处理 SQL。
  4. 性能优化

    • 在执行分页查询时,通过设置合理的参数,能够减少查询的时间复杂度,提高查询效率。

关键参数

  • DbType:指定数据库类型,影响生成的分页 SQL 语句。例如,DbType.MYSQL​ 会生成适用于 MySQL 的分页语句。
  • setOverflow:允许配置是否允许请求的页码超出最大页码范围(例如,返回最后一页的数据)。
  • setMaxLimit:可以设置每页最大记录数,避免用户请求过大的分页数据。

2.2 使用

配置插件

@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {
   

    /**
     * 添加分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
   
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
        // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
        return interceptor;
    }
}

分页查询

Page<User> page = new Page<>(1, 10);  // 当前页, 每页记录数
IPage<User> userPage = userMapper.selectPage(page, null);

三、性能分析插件(PerformanceInterceptor​)

3.1 关于

简介

性能分析插件(PerformanceInterceptor​)是 MyBatis-Plus 提供的一个非常有用的工具,它可以用来监控 SQL 语句的执行时间,帮助开发者及时发现和优化慢查询问题。

3.2 使用

配置插件

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PerformanceInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {
   

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
   
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加性能分析插件
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        performanceInterceptor.setMaxTime(1000); // 设置SQL最大执行时间,单位为毫秒
        interceptor.addInnerInterceptor(performanceInterceptor);
        return interceptor;
    }
}

配置日志输出

为了更好地监控 SQL 语句的执行情况,可以配置日志输出。在 application.properties​ 或 application.yml​ 文件中添加日志配置:

logging:
  level:
    com.baomidou.mybatisplus: DEBUG

  • SQL 执行时间记录:每次执行 SQL 语句时,插件会记录执行时间。
  • 超时处理:如果 SQL 语句的执行时间超过 setMaxTime​ 方法设置的阈值(默认为 0,表示不限制),插件会记录一条警告日志或抛出异常,具体行为取决于配置。

如果 SQL 语句执行时间超过设定的阈值,日志输出可能如下所示:

2024-11-08 10:41:00 [http-nio-8080-exec-1] WARN  c.b.mybatisplus.extension.plugins.inner.PerformanceInterceptor - [performance] SQL Execution Time: 1500 ms

通过以上步骤,你可以在 MyBatis-Plus 中轻松配置和使用性能分析插件,帮助你及时发现和优化慢查询问题。

四、防全表更新与删除插件(BlockAttackInterceptor​)

4.1 关于

简介

MyBatis-Plus 提供了一个防全表更新与删除插件(BlockAttackInterceptor​),该插件可以防止在没有 WHERE 条件的情况下执行全表更新或删除操作,从而避免误操作导致的数据丢失或损坏

使用

配置插件

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {
   

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
   
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加防全表更新与删除插件
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        return interceptor;
    }
}

测试

在控制器层中调用 Service 层的方法进行查询。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/users")
public class UserController {
   

    @Autowired
    private UserService userService;

    @PostMapping("/delete-all")
    public String deleteAllUsers() {
   
        try {
   
            userService.remove(null); // 尝试删除所有用户
            return "All users deleted successfully";
        } catch (Exception e) {
   
            return "Failed to delete all users: " + e.getMessage();
        }
    }

    @PostMapping("/update-all")
    public String updateAllUsers() {
   
        try {
   
            User user = new User();
            user.setName("Updated Name");
            userService.updateById(user); // 尝试更新所有用户
            return "All users updated successfully";
        } catch (Exception e) {
   
            return "Failed to update all users: " + e.getMessage();
        }
    }
}
  1. 尝试删除所有用户:访问 /users/delete-all​ 接口。

    • 如果没有 WHERE 条件,插件会抛出异常并阻止删除操作。

    • 控制台输出示例:

      Failed to delete all users: Cannot execute delete operation without where condition!
      
  2. 尝试更新所有用户:访问 /users/update-all​ 接口。

    • 如果没有 WHERE 条件,插件会抛出异常并阻止更新操作。

    • 控制台输出示例:

      Failed to update all users: Cannot execute update operation without where condition!
      

五、自定义插件

如果内置插件不能满足需求,可以自定义插件。自定义插件需要实现 Interceptor​ 或 InnerInterceptor​ 接口,并在 intercept​ 方法中实现自定义逻辑。

示例:

import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;

import java.sql.Connection;

@Intercepts({
   @Signature(type = StatementHandler.class, method = "prepare", args = {
   Connection.class, Integer.class})})
public class CustomInterceptor implements Interceptor {
   

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
   
        // 自定义逻辑
        System.out.println("CustomInterceptor: Before SQL execution");
        Object result = invocation.proceed();
        System.out.println("CustomInterceptor: After SQL execution");
        return result;
    }

    @Override
    public Object plugin(Object target) {
   
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
   
        Interceptor.super.setProperties(properties);
    }
}

注册自定义插件:

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
   
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new CustomInterceptor());
    return interceptor;
}

通过上述机制和接口,MyBatis-Plus 提供了灵活的插件扩展能力,使开发者可以根据具体需求定制化功能。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
8天前
|
SQL 安全 Java
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。
10 1
MyBatis-Plus条件构造器:构建安全、高效的数据库查询
|
7天前
|
XML 数据库 数据格式
数据库 校验名称唯一性,用于新增和修改功能
数据库 校验名称唯一性,用于新增和修改功能
21 1
|
25天前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
40 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
|
9天前
|
XML 数据库 数据格式
数据库 校验名称唯一性,用于新增和修改功能
数据库 校验名称唯一性,用于新增和修改功能
12 0
|
23天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
56 3
Mysql(4)—数据库索引
|
8天前
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。同时,文章还对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据需求选择最合适的方法。通过具体案例,展示了编译源码安装的灵活性和定制性。
45 2
|
11天前
|
存储 关系型数据库 MySQL
MySQL vs. PostgreSQL:选择适合你的开源数据库
在众多开源数据库中,MySQL和PostgreSQL无疑是最受欢迎的两个。它们都有着强大的功能、广泛的社区支持和丰富的生态系统。然而,它们在设计理念、性能特点、功能特性等方面存在着显著的差异。本文将从这三个方面对MySQL和PostgreSQL进行比较,以帮助您选择更适合您需求的开源数据库。
52 4
|
17天前
|
存储 关系型数据库 MySQL
如何在MySQL中创建数据库?
【10月更文挑战第16天】如何在MySQL中创建数据库?
|
21天前
|
SQL Oracle 关系型数据库
安装最新 MySQL 8.0 数据库(教学用)
安装最新 MySQL 8.0 数据库(教学用)
93 4