MyBatis-Plus 提供了强大的功能扩展机制,其中 BlockAttackInnerInterceptor 是防止全表更新或删除操作的安全插件。在生产环境中,误操作如 UPDATE table SET column = valueDELETE FROM table 而不带 WHERE 条件,可能导致灾难性后果。

一、核心概念

1. 什么是 BlockAttackInnerInterceptor

  • BlockAttackInnerInterceptor 是 MyBatis-Plus 内置的 SQL 拦截器(Interceptor),用于拦截没有 WHERE 条件的 UPDATEDELETE 操作。
  • 当检测到全表更新或删除时,抛出异常,阻止执行,防止误操作导致数据丢失。
  • 属于 InnerInterceptor 接口实现类,通过 MyBatis-Plus 的插件机制注入执行流程。

2. 适用场景

  • 生产环境防止误删/误更。
  • 开发、测试环境调试时可选择性关闭。
  • 多人协作项目中统一安全策略。

二、操作步骤(非常详细)

步骤 1:引入 MyBatis-Plus 依赖

确保项目中已正确引入 MyBatis-Plus(以 Spring Boot 为例):

<!-- Maven -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.5</version> <!-- 推荐使用最新稳定版 -->
</dependency>

步骤 2:创建 MyBatis Plus 配置类

创建一个配置类(如 MyBatisPlusConfig.java),注册拦截器。

package com.example.config;

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 {

    /**
     * 配置 MyBatis-Plus 插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 添加防止全表更新与删除的拦截器
        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());

        return interceptor;
    }
}

步骤 3:验证拦截器是否生效

编写一个测试用例,尝试执行无条件删除:

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public void badDelete() {
        // ❌ 危险操作:无 WHERE 条件的删除
        userMapper.delete(null); // 或 new QueryWrapper<>()
    }
}

执行时将抛出异常:

Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: 
Prohibition of full table deletion, must have where condition

✅ 表明插件已生效,成功阻止全表删除。


三、常见错误与解决方案

错误现象 原因 解决方案
插件未生效,仍可全表删除 未正确注册 MybatisPlusInterceptor 检查配置类是否被 Spring 扫描,@Configuration 是否遗漏
启动报错 ClassNotFoundException 版本不兼容或依赖缺失 升级 MyBatis-Plus 至 3.4.0+,确认依赖完整
其他 SQL 报错或拦截异常 拦截器顺序冲突 BlockAttackInnerInterceptor 通常无需调整顺序,若与其他插件共用,注意添加顺序
测试环境也需要放行 生产安全策略影响开发调试 使用条件注入或配置开关

四、注意事项

  1. 版本要求

    • BlockAttackInnerInterceptorMyBatis-Plus 3.4.0 版本引入。
    • 低于此版本请升级。
  2. 仅拦截 UPDATE/DELETE

    • 不影响 SELECT 操作。
    • INSERT 操作不受影响。
  3. Wrapper 为空时触发拦截

    • 当传入 null 或空 Wrapper(如 new QueryWrapper<>())时,视为无条件操作。
  4. 逻辑删除不受影响

    • 若使用 @TableLogic,逻辑删除仍需条件,否则也会被拦截。

五、使用技巧

技巧 1:按环境启用/禁用插件

@Bean
@ConditionalOnProperty(name = "mybatis-plus.block-attack.enable", havingValue = "true", matchIfMissing = true)
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
    return interceptor;
}

配置文件中控制:

# application-prod.yml
mybatis-plus:
  block-attack:
    enable: true

# application-dev.yml
mybatis-plus:
  block-attack:
    enable: false

⚠️ 建议生产环境强制开启,开发环境可关闭便于调试。

技巧 2:自定义提示信息(需扩展)

原生不支持自定义异常信息,但可通过继承或 AOP 捕获异常后包装:

@ExceptionHandler(MybatisPlusException.class)
public ResponseEntity<?> handleMybatisPlusException(MybatisPlusException e) {
    if (e.getMessage().contains("Prohibition of full table deletion")) {
        return ResponseEntity.badRequest().body("禁止执行无条件删除操作,请检查 WHERE 条件");
    }
    return ResponseEntity.status(500).body("数据库操作异常");
}

六、最佳实践

  1. 生产环境必须开启
    所有生产部署必须启用 BlockAttackInnerInterceptor,作为数据安全第一道防线。

  2. 结合代码审查与权限控制
    插件是最后一道防线,开发阶段应通过代码规范、CR(Code Review)避免写出无条件操作。

  3. 日志监控
    拦截异常应记录日志,便于审计和排查误操作尝试。

  4. 单元测试覆盖
    编写测试用例验证插件行为,确保配置正确。


七、性能优化

  • BlockAttackInnerInterceptor 性能开销极低,仅在 SQL 构建时检查 WHERE 条件是否存在。
  • 无额外数据库查询或复杂计算。
  • 无需担心性能影响,建议始终开启。

八、总结

项目 内容
插件名称 BlockAttackInnerInterceptor
作用 防止全表 UPDATE / DELETE
注册方式 通过 MybatisPlusInterceptor.addInnerInterceptor()
最低版本 MyBatis-Plus 3.4.0
是否影响性能 几乎无影响
推荐使用场景 所有生产环境

一句话总结
在 MyBatis-Plus 配置类中注册 BlockAttackInnerInterceptor,即可轻松防止全表更新与删除,是保障数据安全的必备配置。