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

打印 上一主题 下一主题

主题 968|帖子 968|积分 2904

一、关于Mybatis-Plus插件

1.1 简介

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


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​ 方法,允许在这些方法实验前后插入自界说逻辑。


属性

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

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 设置示例
  1. @Configuration
  2. @MapperScan("scan.your.mapper.package")
  3. public class MybatisPlusConfig {
  4.     /**
  5.      * 添加分页插件
  6.      */
  7.     @Bean
  8.     public MybatisPlusInterceptor mybatisPlusInterceptor() {
  9.         MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  10.         interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  11.         return interceptor;
  12.     }
  13. }
复制代码

设置多个插件
  1. @Configuration
  2. public class MyBatisPlusConfig {
  3.     @Bean
  4.     public MybatisPlusInterceptor mybatisPlusInterceptor() {
  5.         MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  6.         // 添加分页插件
  7.         interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  8.         // 添加性能分析插件
  9.         PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
  10.         performanceInterceptor.setMaxTime(1000); // 设置SQL最大执行时间,单位为毫秒
  11.         interceptor.addInnerInterceptor(performanceInterceptor);
  12.         // 添加防全表更新与删除插件
  13.         interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
  14.         return interceptor;
  15.     }
  16. }
复制代码
注意
使用多个插件时,需要注意它们的顺序。建议的顺序是:

  • 多租户、动态表名
  • 分页、乐观锁
  • SQL 性能规范、防止全表更新与删除
总结:对 SQL 进行单次改造的插件应优先放入,不对 SQL 进行改造的插件最后放入。


二、分页插件(PaginationInnerInterceptor​)

2.1 关于

简介

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


主要功能


  • 自动分页

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

  • 兼容性

    • 支持多种数据库的分页语法,确保在差异数据库上都能正常工作。

  • 动态参数

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

  • 性能优化

    • 在实验分页查询时,通过设置合理的参数,可以或许减少查询的时间复杂度,提高查询效率。


关键参数


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

2.2 使用

设置插件
  1. @Configuration
  2. @MapperScan("scan.your.mapper.package")
  3. public class MybatisPlusConfig {
  4.     /**
  5.      * 添加分页插件
  6.      */
  7.     @Bean
  8.     public MybatisPlusInterceptor mybatisPlusInterceptor() {
  9.         MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  10.         interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
  11.         // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
  12.         return interceptor;
  13.     }
  14. }
复制代码

分页查询
  1. Page<User> page = new Page<>(1, 10);  // 当前页, 每页记录数
  2. IPage<User> userPage = userMapper.selectPage(page, null);  
复制代码


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

3.1 关于

简介

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

3.2 使用

设置插件
  1. import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
  2. import com.baomidou.mybatisplus.extension.plugins.inner.PerformanceInterceptor;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. @Configuration
  6. public class MyBatisPlusConfig {
  7.     @Bean
  8.     public MybatisPlusInterceptor mybatisPlusInterceptor() {
  9.         MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  10.         // 添加性能分析插件
  11.         PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
  12.         performanceInterceptor.setMaxTime(1000); // 设置SQL最大执行时间,单位为毫秒
  13.         interceptor.addInnerInterceptor(performanceInterceptor);
  14.         return interceptor;
  15.     }
  16. }
复制代码

设置日志输出

为了更好地监控 SQL 语句的实验情况,可以设置日志输出。在 application.properties​ 或 application.yml​ 文件中添加日志设置:
  1. logging:
  2.   level:
  3.     com.baomidou.mybatisplus: DEBUG
复制代码


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

如果 SQL 语句实验时间凌驾设定的阈值,日志输出可能如下所示:
  1. 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 条件的情况下实验全表更新或删除操作,从而制止误操作导致的数据丢失或损坏

使用

设置插件
  1. import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
  2. import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. @Configuration
  6. public class MyBatisPlusConfig {
  7.     @Bean
  8.     public MybatisPlusInterceptor mybatisPlusInterceptor() {
  9.         MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  10.         // 添加防全表更新与删除插件
  11.         interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
  12.         return interceptor;
  13.     }
  14. }
复制代码

测试

在控制器层中调用 Service 层的方法进行查询。
  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.web.bind.annotation.DeleteMapping;
  3. import org.springframework.web.bind.annotation.PostMapping;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RestController;
  6. import java.util.List;
  7. @RestController
  8. @RequestMapping("/users")
  9. public class UserController {
  10.     @Autowired
  11.     private UserService userService;
  12.     @PostMapping("/delete-all")
  13.     public String deleteAllUsers() {
  14.         try {
  15.             userService.remove(null); // 尝试删除所有用户
  16.             return "All users deleted successfully";
  17.         } catch (Exception e) {
  18.             return "Failed to delete all users: " + e.getMessage();
  19.         }
  20.     }
  21.     @PostMapping("/update-all")
  22.     public String updateAllUsers() {
  23.         try {
  24.             User user = new User();
  25.             user.setName("Updated Name");
  26.             userService.updateById(user); // 尝试更新所有用户
  27.             return "All users updated successfully";
  28.         } catch (Exception e) {
  29.             return "Failed to update all users: " + e.getMessage();
  30.         }
  31.     }
  32. }
复制代码

  • 实验删除所有用户:访问 /users/delete-all​ 接口。

    • 如果没有 WHERE 条件,插件会抛出异常并阻止删除操作。
    • 控制台输出示例:
      1. Failed to delete all users: Cannot execute delete operation without where condition!
      复制代码

  • 实验更新所有用户:访问 /users/update-all​ 接口。

    • 如果没有 WHERE 条件,插件会抛出异常并阻止更新操作。
    • 控制台输出示例:
      1. Failed to update all users: Cannot execute update operation without where condition!
      复制代码



五、自界说插件

如果内置插件不能满足需求,可以自界说插件。自界说插件需要实现 Interceptor​ 或 InnerInterceptor​ 接口,并在 intercept​ 方法中实现自界说逻辑。
示例:
  1. import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
  2. import org.apache.ibatis.executor.statement.StatementHandler;
  3. import org.apache.ibatis.plugin.Interceptor;
  4. import org.apache.ibatis.plugin.Intercepts;
  5. import org.apache.ibatis.plugin.Invocation;
  6. import org.apache.ibatis.plugin.Signature;
  7. import java.sql.Connection;
  8. @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
  9. public class CustomInterceptor implements Interceptor {
  10.     @Override
  11.     public Object intercept(Invocation invocation) throws Throwable {
  12.         // 自定义逻辑
  13.         System.out.println("CustomInterceptor: Before SQL execution");
  14.         Object result = invocation.proceed();
  15.         System.out.println("CustomInterceptor: After SQL execution");
  16.         return result;
  17.     }
  18.     @Override
  19.     public Object plugin(Object target) {
  20.         return Interceptor.super.plugin(target);
  21.     }
  22.     @Override
  23.     public void setProperties(Properties properties) {
  24.         Interceptor.super.setProperties(properties);
  25.     }
  26. }
复制代码
注册自界说插件:
  1. @Bean
  2. public MybatisPlusInterceptor mybatisPlusInterceptor() {
  3.     MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  4.     interceptor.addInnerInterceptor(new CustomInterceptor());
  5.     return interceptor;
  6. }
复制代码
通过上述机制和接口,MyBatis-Plus 提供了灵活的插件扩展能力,使开发者可以根据具体需求定制化功能。



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

笑看天下无敌手

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表