MyBatis-Plus 插件

发布于:2025-08-14 ⋅ 阅读:(38) ⋅ 点赞:(0)

MyBatis-Plus 基于 MyBatis 的插件机制,提供了一系列实用插件,可快速实现分页、防全表操作、乐观锁等功能。这些插件通过拦截 SQL 执行流程,在不侵入业务代码的前提下增强框架能力。

一、MyBatis-Plus 插件机制基础

1. 插件原理

MyBatis 的插件机制基于 JDK 动态代理,通过拦截 ExecutorStatementHandlerParameterHandlerResultSetHandler 四个核心接口的方法,在 SQL 执行的关键节点插入自定义逻辑。

MyBatis-Plus 的插件均实现 InnerInterceptor 接口,通过 MybatisPlusInterceptor 拦截器链统一管理,只需简单配置即可生效。

2. 插件注册方式

所有插件需通过 MybatisPlusInterceptor 注册,示例如下:

@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 注册插件(可添加多个)
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // 防全表操作插件
        return interceptor;
    }
}

二、核心插件案例

1. 分页插件(PaginationInnerInterceptor)

分页是数据库操作的高频需求,MyBatis-Plus 分页插件可自动拼接分页 SQL,无需手动编写 LIMIT 语句。

配置步骤:
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    // 指定数据库类型(MySQL)
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    return interceptor;
}
分页查询示例:
@Test
public void testPage() {
    // 创建分页条件:第1页(从0开始),每页2条数据
    Page<Student> page = new Page<>(0, 2);
    // 执行分页查询(第二个参数为查询条件,可传null)
    IPage<Student> resultPage = studentMapper.selectPage(page, null);
    
    // 分页结果解析
    System.out.println("总条数:" + resultPage.getTotal());
    System.out.println("总页数:" + resultPage.getPages());
    System.out.println("当前页数据:" + resultPage.getRecords());
}
原理:

插件会拦截 Executorquery 方法,根据数据库类型自动在 SQL 后拼接分页语句(如 MySQL 的 LIMIT),同时查询总条数,封装成 IPage 对象返回。

2. 防止全表更新与删除插件(BlockAttackInnerInterceptor)

该插件用于拦截全表更新或删除操作,避免因误操作导致的数据丢失,适合开发环境使用。

配置步骤:
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
    // 添加防全表操作插件
    interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
    return interceptor;
}
拦截效果:

当执行无条件的全表更新/删除时,插件会抛出异常:

// 全表删除(会被拦截)
@Test
public void testDeleteAll() {
    // 无查询条件的删除会触发拦截
    studentMapper.delete(new QueryWrapper<>()); 
}

执行后会抛出 BlockAttackException,提示“不允许全表删除”。

注意:
  • 仅支持 MySQL 5.6.3 以上版本;
  • 生产环境建议谨慎使用,避免影响正常业务操作。

3. 乐观锁插件(OptimisticLockerInnerInterceptor)

乐观锁用于解决并发场景下的数据冲突,通过版本号机制实现:更新时检查版本号,若一致则更新并递增版本号,否则更新失败。

实现步骤:
(1)配置插件:
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    // 其他插件...
    // 添加乐观锁插件
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}
(2)实体类添加版本字段:
@Data
public class Student {
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
    // 版本字段,添加@Version注解
    @Version
    private Integer version; 
}
(3)数据库添加版本列:
ALTER TABLE student ADD COLUMN version INT DEFAULT 0;
(4)测试乐观锁:
@Test
public void testOptimisticLock() {
    // 1. 查询数据(获取当前版本号)
    Student student = studentMapper.selectById(1); // version=0
    
    // 2. 模拟并发更新
    Student student2 = studentMapper.selectById(1); // 另一个线程也获取version=0
    
    // 线程1更新(成功,version变为1)
    student.setName("线程1更新");
    studentMapper.updateById(student);
    
    // 线程2更新(失败,版本号已变化)
    student2.setName("线程2更新");
    int rows = studentMapper.updateById(student2); 
    System.out.println("线程2更新影响行数:" + rows); // 输出0,更新失败
}

三、插件执行顺序与冲突处理

  1. 执行顺序
    插件在 MybatisPlusInterceptor 中的添加顺序即执行顺序,建议按“分页插件 → 防全表操作插件 → 乐观锁插件”的顺序配置。

  2. 冲突处理

    • 乐观锁插件与防全表操作插件可同时使用,无冲突;
    • 若自定义插件与内置插件功能重叠,需注意拦截逻辑的优先级。

四、自定义插件扩展

除内置插件外,可通过实现 InnerInterceptor 接口开发自定义插件。例如,实现一个 SQL 日志打印插件:

public class SqlLogInterceptor implements InnerInterceptor {
    @Override
    public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
        // 获取SQL语句
        BoundSql boundSql = sh.getBoundSql();
        String sql = boundSql.getSql();
        System.out.println("执行SQL:" + sql);
    }
}

// 注册自定义插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new SqlLogInterceptor()); // 自定义插件
    return interceptor;
}

总结

MyBatis-Plus 插件体系通过拦截 SQL 执行流程,提供了分页、防全表操作、乐观锁等实用功能,大幅简化了开发工作。核心插件的使用需注意:

  • 分页插件需指定数据库类型,确保分页语句正确;
  • 防全表操作插件适合开发环境,防止误操作;
  • 乐观锁通过版本号机制解决并发冲突,需正确配置版本字段。

网站公告

今日签到

点亮在社区的每一天
去签到