MyBatis-Plus 与扩展与 MyBatis 与 Spring 集成

共 32 题
📑 题目列表 32 题
#
★★★

1. MyBatis 与 Spring AOP 的协作(事务边界)

请说明 MyBatis 与 Spring AOP 的协作,特别是在事务边界上的配合?

  • 事务边界与 SqlSession 的绑定
  • Spring AOP 的 @Transactional 代理
  • SqlSessionTemplate 的事务感知

MyBatis 与 Spring 集成时,SqlSessionTemplate 会感知当前 Spring 事务:当方法被 @Transactional 标记(由 Spring AOP 代理处理)时,事务内共用一个 SqlSession(绑定到事务),事务结束提交/回滚并释放连接。Spring AOP 的事务拦截器在方法进入时开启事务、绑定 SqlSession,方法退出时提交/回滚,从而划定了事务边界与 SqlSession 生命周期。MyBatis 的一系列操作(Mapper 调用)都在这个事务边界内执行,共享同一连接,保证一致性。若事务边界外调用,则每个操作开启独立 SqlSession。

事务边界由 Spring AOP 划定,SqlSession 绑定到该事务。理解"事务内单例 SqlSession"与 AOP 代理的配合,是掌握 MyBatis-Spring 事务语义的关键。需注意自调用、非 public 方法等会使 AOP 代理失效。

#
★★★

2. MyBatis 与 Spring Boot Actuator 的指标集成

请说明 MyBatis 与 Spring Boot Actuator 的指标集成?

  • Actuator 指标暴露
  • 连接池/执行指标
  • 监控与调优

通过 Actuator 的 Micrometer 指标,可监控 MyBatis 相关的连接池(如 HikariCP 的 active/idle 连接数)、数据源与数据访问健康状态。MyBatis 自身的 Mapper 执行次数、耗时等可通过自定义拦截器或 Actuator 暴露的指标通道接入。此外,Actuator 提供 /health、/metrics 端点,可结合 Druid StatView 或 Hikari 指标暴露连接池状态。集成后运维可实时观测数据访问层健康与容量。

指标集成把连接池、数据访问层纳入监控体系。理解连接池指标(active/idle/pending)、执行耗时与健康检查,可辅助容量规划与问题定位。

#
★★★

3. MyBatis 与 Spring 事务的集成(SpringManagedTransaction)

请说明 MyBatis 与 Spring 事务的集成机制(SpringManagedTransaction)?

  • SpringManagedTransaction 的作用
  • 事务管理器的协调
  • 连接管理与提交回滚

MyBatis 与 Spring 集成时,使用 SpringManagedTransaction 作为事务实现,它从 Spring 事务管理器(DataSourceTransactionManager)获取连接,并交由 Spring 统一管理事务的开启、提交、回滚与连接释放。这样 MyBatis 的 SqlSession 与 Spring 事务共享同一连接与事务边界,避免 MyBatis 自带事务与 Spring 事务冲突。SpringManagedTransaction 通过事务同步(TransactionSynchronizationManager)跟踪当前事务连接,保证事务内 MyBatis 操作与 Spring 管理一致。

SpringManagedTransaction 让 MyBatis 融入 Spring 事务体系,是集成的关键。理解它可避免"MyBatis 自管事务"与"Spring 事务"冲突,保证事务边界一致。

#
★★★

4. MyBatis 拦截器链与 Spring Bean 的协作

请说明 MyBatis 拦截器链与 Spring Bean 的协作?

  • 拦截器注入 Spring 容器
  • 拦截器链与 Spring 依赖
  • 拦截器中注入 Service 的注意

MyBatis 拦截器(Interceptor)可以作为 Spring Bean 注入到 SqlSessionFactory 中,MyBatis 会为它们创建代理并组建拦截器链。拦截器在 Spring 容器中可通过 @Autowired 注入其他 Bean(如 Redis、Service)用于业务逻辑(如分页、缓存、加解密)。但需注意:拦截器在 Spring 容器初始化时可能先于某些 Bean 创建,且拦截器实例被 MyBatis 共享,需保证线程安全与无状态或线程安全依赖。拦截器链的协作遵循责任链顺序,每个拦截器可访问 Spring 注入的依赖实现横切逻辑。

拦截器作为 Spring Bean 可复用 Spring 的依赖注入能力。理解其生命周期与线程安全,可正确编写依赖 Service 的拦截器(如分页 count、缓存读写)。

#
★★★

5. MyBatis 的 SqlSessionFactoryBean 配置

请说明 MyBatis 的 SqlSessionFactoryBean 配置?

  • SqlSessionFactoryBean 的属性
  • 数据源、Mapper XML、插件、类型处理器的配置
  • 与 Spring Boot 自动配置的关系

SqlSessionFactoryBean 是 Spring 中构建 SqlSessionFactory 的工厂 Bean,可配置 dataSource、mapperLocations(XML 路径)、typeAliasesPackage、typeHandlersPackage、plugins(拦截器)、configurationProperties、environment 等。它在容器初始化时构建 SqlSessionFactory,供 SqlSessionTemplate 使用。Spring Boot 的 mybatis-spring-boot-starter 会自动配置 SqlSessionFactoryBean(从 application.properties 读取配置),复杂场景可自定义覆盖。正确配置 mapper 扫描与插件是集成关键。

SqlSessionFactoryBean 是 MyBatis-Spring 集成的装配点。理解其配置项(数据源、XML、插件、类型处理器)可定制 MyBatis 行为,避免插件未注册、Mapper 未扫描等问题。

#
★★★

6. MyBatis-Plus 与 Spring Boot 4.x 的兼容性

请说明 MyBatis-Plus 与 Spring Boot 4.x 的兼容性?

  • 版本兼容性
  • Spring Boot 4.x 的依赖变更
  • 升级注意事项

MyBatis-Plus 需要选择与 Spring Boot 主要版本匹配的版本。Spring Boot 4.x 升级到 Jakarta EE 11、Spring Framework 7,可能引入 API 与依赖变化,MyBatis-Plus 需发布对应兼容版本(如基于 mybatis-spring 新版本)。升级时需注意:mybatis-spring-boot-starter 的版本协调、mybatis-spring 的 API 变化、以及 MyBatis-Plus 的自动配置与新 Spring Boot 自动配置机制的兼容。使用 Spring Boot 4.x 前应确认 MyBatis-Plus 官方支持版本,避免依赖不兼容。

框架兼容性是升级的关键。MyBatis-Plus 依赖 mybatis-spring 与 Spring Boot 自动配置,主版本升级需同步升级组件并验证功能。理解版本约束可避免启动失败或功能异常。

#
★★★

7. MyBatis-Plus 的 BaseMapper/IService 抽象

请说明 MyBatis-Plus 的 BaseMapper 与 IService 抽象?

  • BaseMapper 的通用 CRUD
  • IService 与 ServiceImpl 的服务层抽象
  • 与实体/泛型的关联

BaseMapper 是 MyBatis-Plus 提供的通用 Mapper 接口,内置 insert、deleteById、updateById、selectById、selectList 等通用 CRUD 方法,通过泛型绑定实体 T,无需手写 SQL。IService 是服务层接口,提供批量操作、链式查询、逻辑删除等能力,ServiceImpl 为其默认实现。BaseMapper 面向数据访问层,IService 面向服务层,二者配合简化 CRUD 开发。它们底层通过 SqlInjector 注入通用 SQL 到 MappedStatement。

BaseMapper/IService 是"约定接口 + 自动注入 SQL"的抽象,减少样板代码。理解其泛型绑定与内置方法,可高效使用 MyBatis-Plus 的通用能力。

#
★★★

8. MyBatis-Plus 的乐观锁插件(OptimisticLockerInnerInterceptor)

请说明 MyBatis-Plus 的乐观锁插件(OptimisticLockerInnerInterceptor)?

  • 乐观锁插件的机制
  • @Version 字段
  • 更新断言与失败处理

MyBatis-Plus 的 OptimisticLockerInnerInterceptor 实现乐观锁:实体字段标注 @Version 后,更新时插件会在 SQL 中追加 version 校验条件(如 WHERE ... AND version = 旧值),并将 version 自增,若受影响行数为 0 则更新失败。该插件通过拦截 update 语句自动完成版本校验与更新,无需手写条件。使用需配合 @Version 注解与实体版本字段,注意插入时版本字段初始值。乐观锁适合并发冲突少的场景,失败由业务层处理重试。

乐观锁插件把"版本号 CAS 校验"自动化到 SQL 层。理解其 WHERE 追加版本条件与自增机制,可正确实现乐观并发控制并处理更新失败。

@Version
private Integer version;
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor i = new MybatisPlusInterceptor();
    i.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return i;
}
#
★★★

9. SqlSessionTemplate 与线程安全的 SqlSession

请说明 SqlSessionTemplate 与线程安全的 SqlSession?

  • SqlSessionTemplate 的线程安全
  • 与 MyBatis 原生 SqlSession 的区别
  • 事务绑定

MyBatis 原生的 SqlSession 是线程不安全的,每次使用需创建并在结束时关闭。SqlSessionTemplate 是 Spring 提供的线程安全 SqlSession 代理,内部按需获取 SqlSession(事务内复用、非事务独立),执行后自动归还连接,避免手动管理。SqlSessionTemplate 通过 ThreadLocal/事务同步绑定当前事务的 SqlSession,保证同一事务内操作共享同一条连接。它是 MyBatis 与 Spring 整合时 Mapper 调用的实际实现,解决了线程安全与连接管理问题。

SqlSessionTemplate 把"每次操作一个 SqlSession"的职责交给 Spring,实现线程安全与事务绑定。理解其代理与事务同步机制,可正确理解 MyBatis-Spring 的会话管理。

#
★★★

10. LambdaQueryWrapper 的类型安全优势

请说明 MyBatis-Plus 的 LambdaQueryWrapper 的类型安全优势?

  • LambdaQueryWrapper 的 lambda 引用
  • 编译期校验属性
  • 相比字符串列名的优势

LambdaQueryWrapper 使用 Lambda 表达式(方法引用)引用实体属性(如 User::getAge),在编译期校验属性是否存在,避免字符串列名拼写错误导致的运行时错误。相比 QueryWrapper 用字符串("age")指定列名,Lambda 版本重构安全、类型安全、可读性好。它基于 MyBatis-Plus 的 Lambda 元数据解析(通过反射获取属性名与列名映射),支持条件构造、排序、分组等。命名引用随重构自动更新,提升可维护性。

Lambda 引用把"列名"从魔法字符串变为编译期类型安全的方法引用。理解其实现(反射解析属性名)与优势,可编写更健壮的动态查询。

new LambdaQueryWrapper<User>()
    .eq(User::getAge, 18)
    .like(User::getName, "tom")
    .orderByDesc(User::getId);
#
★★

11. MapperScannerConfigurer 的包扫描机制

请说明 MapperScannerConfigurer 的包扫描机制?

  • 包扫描注册 Mapper Bean
  • basePackage 与注解过滤
  • 与 @MapperScan 的关系

MapperScannerConfigurer 是 Spring 中扫描 Mapper 接口的 BeanDefinitionRegistryPostProcessor,它扫描指定包(basePackage)下的 Mapper 接口,为每个接口注册一个 MapperFactoryBean(生成动态代理),并注册到 Spring 容器供注入。它支持通过注解过滤(如 @Mapper)与接口过滤。@MapperScan 注解是 MapperScannerConfigurer 的便捷封装,作用相同。扫描后 Mapper 接口可被 @Autowired 注入使用。

包扫描把 Mapper 接口转化为可注入的 Spring Bean。理解扫描机制与过滤规则,可避免 Mapper 未注册或重复注册问题。

#
★★

12. MyBatis 与 Druid 连接池的协作

请说明 MyBatis 与 Druid 连接池的协作?

  • Druid 作为数据源
  • 连接池与 SqlSession 的配合
  • 监控与 SQL 日志

MyBatis 配置 Druid 作为数据源(DataSource),SqlSessionFactory 通过该数据源获取连接。Druid 提供连接池管理(连接复用、健康检查、泄漏检测)、SQL 监控(StatViewServlet)、SQL 防火墙(WallFilter)等能力。MyBatis 执行 SQL 时从 Druid 获取连接,事务控制由 Spring 事务管理器协调。Druid 的监控可看到 MyBatis 执行的 SQL 与连接使用情况,辅助性能调优。二者协作是"MyBatis 执行 SQL + Druid 管理连接与监控"。

连接池与 ORM 的协作重点是连接获取、监控与泄漏管理。Druid 的 SQL 监控与连接池指标对 MyBatis 性能分析很有价值。

#
★★

13. MyBatis 与 JdbcTemplate 的边界

请说明 MyBatis 与 JdbcTemplate 的边界?

  • JdbcTemplate 的轻量 JDBC 封装
  • MyBatis 的映射能力
  • 选型

JdbcTemplate 是 Spring 提供的轻量 JDBC 封装,提供 execute、query、update 等方法,简化 JDBC 资源管理与异常转换,但结果映射需手动(RowMapper)。MyBatis 是完整持久层框架,提供 SQL 映射、ResultMap、动态 SQL、TypeHandler、缓存、插件等。边界:JdbcTemplate 适合简单、直接的 JDBC 访问,MyBatis 适合复杂映射与半自动 ORM。两者可共存,简单场景用 JdbcTemplate,复杂 CRUD 用 MyBatis。

JdbcTemplate 是"轻量 JDBC 工具",MyBatis 是"完整 ORM"。理解二者边界可避免过度设计,选择合适的数据访问方式。

#
★★

14. MyBatis 与 Spring 6 @TransactionalEventListener 的协作

请说明 MyBatis 与 Spring 6 @TransactionalEventListener 的协作?

  • @TransactionalEventListener 的用途
  • 事务提交后处理
  • 与数据访问的配合

@TransactionalEventListener 监听事务生命周期事件(如 AFTER_COMMIT、AFTER_ROLLBACK),在事务提交后执行回调,常用于"事务提交后发送消息、清理缓存、异步通知"。与 MyBatis 协作时,事务内的 MyBatis 操作在提交后,通过 @TransactionalEventListener 触发后续逻辑(如缓存失效、审计发送),保证"数据已提交后再做副作用"。默认在事务提交后同步执行,可配置 fallbackExecution 处理无事务场景。它与 MyBatis 的结合实现在事务边界上做横切后续处理。

@TransactionalEventListener 在事务提交后执行,避免"事务未提交就发消息/清缓存"导致的不一致。理解其提交后语义,可配合 MyBatis 数据变更做一致性的后续处理。

#
★★

15. MyBatis 与 Spring Cloud 的配置中心协作

请说明 MyBatis 与 Spring Cloud 配置中心的协作?

  • 配置中心的动态刷新
  • MyBatis 配置的刷新 @RefreshScope
  • 注意事项

MyBatis 可通过 Spring Cloud Config/Nacos 配置中心管理数据源、Mapper 配置等。使用 @RefreshScope 标注的 Bean 可在配置刷新时重建,从而更新数据源与 MyBatis 配置。但 MyBatis 的 SqlSessionFactory 是重量级单例,配置刷新重建其成本较高,且连接池、Mapper 缓存等需谨慎处理。实践中通常配置中心管理数据源连接参数,通过 @RefreshScope 或事件监听在刷新时重建数据源,但需评估连接池重建风险。动态刷新需权衡稳定性。

配置中心让数据源等配置可动态管理,但 MyBatis 单例的重建成本高。理解 @RefreshScope 与 SqlSessionFactory 生命周期,可安全地将配置中心接入。

#
★★

16. MyBatis 与 Spring Modulith 模块边界

请说明 MyBatis 与 Spring Modulith 模块边界?

  • Spring Modulith 的模块化
  • MyBatis Mapper 的模块归属
  • 事务与依赖边界

Spring Modulith 强调模块化架构,每个模块有明确边界与依赖规则。MyBatis 的 Mapper 接口、XML、实体通常按业务模块划分,Mapper 属于其业务模块,模块间通过服务接口而非直接访问其他模块的 Mapper 协作。事务边界也应遵循模块边界,避免跨模块的多数据库操作导致事务割裂。Spring Modulith 可校验模块依赖,防止模块间越界访问 Mapper。MyBatis 与 Modulith 的协作重点是"模块归位 + 事务边界一致"。

模块化让 Mapper 按模块内聚,事务与依赖边界清晰。理解 Modulith 的依赖约束,可避免 Mapper 跨模块滥用与事务边界混乱。

#
★★

17. MyBatis 多数据源(AbstractRoutingDataSource)

请说明 MyBatis 多数据源(AbstractRoutingDataSource)的实现?

  • AbstractRoutingDataSource 的路由
  • 动态切换数据源
  • 与事务的配合

AbstractRoutingDataSource 是 Spring 提供的动态路由数据源,通过 determineCurrentLookupKey() 返回当前数据源 key,在获取连接时路由到对应 DataSource。MyBatis 使用该数据源时,可结合 ThreadLocal 或 AOP 在运行时切换数据源(如读写分离、按租户路由)。切换需在事务开启前完成,因为事务绑定连接后不再切换。多数据源需配置多个 DataSource 与事务管理器,并注意事务边界与连接归属。

动态路由数据源实现"按上下文选数据源",但需在事务前确定。理解 lookupKey 与事务绑定时机,是正确实现多数据源/读写分离的关键。

#
★★

18. MyBatis 的 @MapperScan 与 @Mapper 的差异

请说明 MyBatis 的 @MapperScan 与 @Mapper 的差异?

  • @Mapper 的单个接口标记
  • @MapperScan 的批量扫描
  • 使用方式

@Mapper 标注在单个 Mapper 接口上,告诉 MyBatis 将该接口注册为 Mapper;@MapperScan 标注在配置类上,扫描指定包下的所有 Mapper 接口,批量注册。使用 @MapperScan 后无需每个接口加 @Mapper。@Mapper 适合少量 Mapper 或需要显式声明,@MapperScan 适合批量、集中管理。二者作用等价(都触发 Mapper 注册),区别是粒度与便捷性。

@Mapper 与 @MapperScan 都是注册 Mapper 的入口,一个是单接口、一个是包扫描。理解二者可避免重复注册或漏注册。

#
★★

19. MyBatis 的 @Transactional 与 Propagation

请说明 MyBatis 的 @Transactional 与 Propagation 传播行为?

  • @Transactional 事务边界
  • Propagation 传播行为
  • 与 MyBatis 的配合

@Transactional 声明事务边界,同样适用于 MyBatis 操作。Propagation 传播行为决定事务的嵌套与边界:REQUIRED(默认,加入已有事务或新建)、REQUIRES_NEW(挂起已有事务,新建独立事务)、NESTED(savepoint 嵌套)、SUPPORTS、NOT_SUPPORTED、MANDATORY、NEVER。MyBatis (SqlSession) 绑定到当前事务,因此传播行为决定 SqlSession 与连接的使用。例如 REQUIRES_NEW 会新建独立事务与连接,需注意连接池占用。MyBatis 与 Spring 事务(@Transactional + Propagation)配合,保证数据一致性。

传播行为控制事务边界与连接占用。MyBatis 在事务内共用 SqlSession/连接,理解传播行为可正确设计嵌套事务与避免连接耗尽。

#
★★

20. MyBatis 的 PageHelper 集成与边界

请说明 MyBatis 的 PageHelper 集成与边界?

  • PageHelper 的集成方式
  • 分页的线程上下文
  • 边界与注意事项

PageHelper 通过 MyBatis 插件机制集成,在 Executor 拦截点自动改写 SQL 为分页查询。它使用 ThreadLocal 保存分页参数,方法调用后自动清理。分页边界:PageHelper 只对紧随其后的第一条查询生效,必须保证分页设置与查询在同一线程、同一方法作用域内,避免跨线程或异步导致分页失效。PageHelper 支持 count 查询与多方言。使用注意:不要在多条查询间误用分页、避免分页参数泄漏到其他线程。

PageHelper 基于 ThreadLocal 的分页上下文,与线程绑定。理解其生效范围与线程边界,可避免分页不生效或数据错乱。

#
★★

21. MyBatis 的多租户与 Spring Security 的协作

请说明 MyBatis 的多租户与 Spring Security 的协作?

  • 租户标识的来源
  • 拦截器注入租户条件
  • 与 Spring Security 上下文配合

多租户通常每个请求需要确定租户标识,Spring Security 上下文(SecurityContext)可保存当前用户/租户信息,MyBatis 通过拦截器(如 MyBatis-Plus 的 TenantLineInnerInterceptor)在 SQL 执行时自动追加租户条件(WHERE tenant_id = ?)。实现时从 Spring Security 上下文获取租户标识,注入到拦截器或上下文变量,使 SQL 自动带租户过滤。需保证租户标识在请求线程内传递,并在异常路径清理。多租户与安全协作的核心是"租户来源 + SQL 自动过滤"。

租户标识通常来自认证信息,MyBatis 拦截器在 SQL 层自动过滤。理解 SecurityContext 与拦截器的配合,可安全实现多租户隔离。

#
★★

22. MyBatis-Plus 与 MyBatis Dynamic DataSource(多数据源)

请说明 MyBatis-Plus 与 MyBatis Dynamic DataSource(多数据源)的配合?

  • 动态数据源切换
  • 读写分离
  • 与 MyBatis-Plus 的集成

MyBatis-Plus 常与 dynamic-datasource-spring-boot-starter 集成,通过 @DS 注解在方法或类上指定数据源,实现读写分离或按业务路由到不同数据源。dynamic-datasource 基于 AbstractRoutingDataSource 实现,结合 AOP 在方法进入时切换数据源。与 MyBatis-Plus 配合时,Mapper 使用对应数据源执行,事务与数据源需协调(切换在事务前)。多数据源需注意事务边界、连接池管理与跨库事务限制。

动态数据源注解切换结合 AOP,实现读写分离与多库路由。理解切换时机与事务边界,可正确使用多数据源。

#
★★

23. MyBatis-Plus 的 SQL 性能分析插件(PerformanceInterceptor)在生产环境的关闭建议

请说明 MyBatis-Plus 的 SQL 性能分析插件(PerformanceInterceptor)在生产环境的关闭建议?

  • PerformanceInterceptor 的作用
  • 生产环境的性能影响
  • 关闭建议

MyBatis-Plus 的 PerformanceInterceptor(用于 SQL 性能分析)会在执行时输出 SQL 耗时与执行情况,方便开发期定位慢 SQL。但该插件在生产环境有性能开销(额外拦截、日志、字符串处理),且可能输出敏感 SQL,官方建议生产环境关闭。生产环境应使用专业的慢查询监控(数据库慢查询日志、APM、连接池监控)替代。开发/测试环境开启辅助定位,生产禁用。

性能分析插件是开发期辅助工具,生产环境的日志与拦截开销不可忽略。理解其定位,选择在合适环境启用,避免生产性能劣化。

#
★★

24. MyBatis-Plus 的 SqlInjector 自定义 SQL

请说明 MyBatis-Plus 的 SqlInjector 自定义 SQL 注入机制?

  • SqlInjector 的作用
  • 自定义方法注入
  • AbstractMethod 的实现

MyBatis-Plus 的 SqlInjector(AbstractSqlInjector)负责向 Mapper 注入通用 SQL 方法(如 selectById、insert)。开发者可通过继承 AbstractSqlInjector 并实现 getMethodList 方法,自定义 AbstractMethod 实现对 Mapper 注入新的 SQL 方法。自定义方法在启动时生成 MappedStatement 注册到 MyBatis,扩展 Mapper 的通用能力。这是 MyBatis-Plus 扩展机制的核心,如 BaseMapper 的通用方法即由默认 SqlInjector 注入。

SqlInjector 通过"注入 SQL 方法"扩展 Mapper 能力,是 MyBatis-Plus 的扩展点。理解其机制可自定义通用 SQL 方法,避免重复手写。

#
★★

25. MyBatis-Plus 的 TenantLineInnerInterceptor 边界

请说明 MyBatis-Plus 的 TenantLineInnerInterceptor 边界?

  • 多租户 SQL 自动过滤
  • 忽略表配置
  • 边界与限制

TenantLineInnerInterceptor 是 MyBatis-Plus 的多租户插件,在 SQL 执行时自动为查询、插入、更新、删除追加租户条件(如 WHERE tenant_id = ?),实现多租户数据隔离。通过 TenantLineHandler 配置租户列名与忽略规则(ignoreTable 指定不参与租户过滤的表,如字典表)。边界:对原生 SQL、某些复杂 SQL、多表 join 可能不完整支持,需配置忽略表;租户字段需在实体中处理。理解其忽略表与 SQL 生成边界,可避免误过滤或漏过滤。

租户插件自动过滤多租户数据,但需配置忽略表与适配复杂 SQL。理解其边界可避免对共享表误加租户条件。

#
★★

26. MyBatis-Plus 的分页插件(PaginationInnerInterceptor)原理

请说明 MyBatis-Plus 的分页插件(PaginationInnerInterceptor)原理?

  • 拦截 query 生成分页 SQL
  • 方言适配
  • count 优化

PaginationInnerInterceptor 是 MyBatis-Plus 的分页插件,通过拦截 Executor 的 query 方法,在执行前基于 IPage 对象解析分页参数,并根据数据库方言(DbType)生成分页 SQL(如 MySQL LIMIT、PostgreSQL LIMIT/OFFSET)。同时自动执行 count 查询(可优化 count 语句)。它是物理分页(数据库层分页),性能好。使用需注册到 MybatisPlusInterceptor,并传入 DbType 或自动识别。分页参数经 IPage 传递,插件在查询后填充 total 等。

分页插件在 SQL 层改写分页,是物理分页的核心。理解其拦截 query、方言与 count 生成,可正确使用与规避分页失效。

#
★★

27. MyBatis-Plus 的多租户插件

请说明 MyBatis-Plus 的多租户插件?

  • 多租户插件的功能
  • 租户条件注入
  • 使用场景

MyBatis-Plus 多租户插件即 TenantLineInnerInterceptor,通过 TenantLineHandler 提供租户列名与租户值,在 SQL 执行时自动为增删改查追加租户条件,实现多租户数据隔离。它支持忽略表(如不做租户隔离的公共表)、自定义租户判断(如忽略某些 SQL)。适用于共享表多租户架构。使用需注册到 MybatisPlusInterceptor,租户值从上下文(如请求头)获取。

多租户插件自动化"租户过滤",减少手写条件。理解其租户来源与忽略表配置,可安全实现多租户隔离。

#
★★

28. MyBatis-Plus 的数据权限插件(DataPermissionInterceptor)

请说明 MyBatis-Plus 的数据权限插件(DataPermissionInterceptor)?

  • 数据权限过滤
  • 按用户/部门过滤 SQL
  • 与拦截器链的配合

DataPermissionInterceptor 用于数据权限过滤,根据当前用户/角色的权限范围,在 SQL 查询时自动追加过滤条件(如 WHERE dept_id IN (用户所属部门) 或仅本人数据)。它通过 DataPermissionHandler 提供过滤方法,按业务规则生成权限条件。与多租户插件类似,但语义是"行级数据权限"而非租户隔离。适用于不同角色看到不同数据范围的场景。需精确配置过滤规则,避免越权或误过滤。

数据权限插件在 SQL 层实现行级权限。理解其按用户/部门生成过滤条件,可安全实现数据权限控制。

#
★★

29. MyBatis-Plus 的核心特性(CRUD Wrapper、分页插件、逻辑删除)

请说明 MyBatis-Plus 的核心特性(CRUD Wrapper、分页插件、逻辑删除)?

  • Wrapper 条件构造
  • 分页插件
  • 逻辑删除

MyBatis-Plus 的核心特性包括:通用 CRUD(BaseMapper/IService 内置方法)、Wrapper 条件构造器(QueryWrapper/LambdaQueryWrapper 动态构造查询/更新条件)、分页插件(PaginationInnerInterceptor 物理分页)、逻辑删除(@TableLogic 自动改写删除为更新标记)、乐观锁(@Version)、字段自动填充、多租户等。这些特性减少样板代码,提升开发效率。逻辑删除通过 @TableLogic 字段,删除时自动改为 UPDATE deleted=1,查询自动过滤已删除记录。

MyBatis-Plus 以"约定 + 自动注入"为核心,Wrapper 动态构造条件、分页物理分页、逻辑删除软删除。理解这些特性可高效使用框架。

#
★★

30. MyBatis-Plus 的防全表更新与删除插件

请说明 MyBatis-Plus 的防全表更新与删除插件?

  • 防全表更新/删除的机制
  • 无 where 条件的拦截
  • 配置方式

MyBatis-Plus 提供防全表更新与删除插件(BlockAttackInnerInterceptor),当检测到更新或删除 SQL 没有 WHERE 条件(或无条件)时,直接抛异常阻止执行,防止误操作清空/更新全表数据。它通过拦截 SQL 检查是否包含 where 条件,无则拦截。适用于生产环境防止手滑的全表操作。配置需在需要保护的场景注册,且对确实需要全表更新的操作需显式加条件或绕过。

防全表插件是"安全护栏",拦截无 where 的更新/删除。理解其触发条件,可避免误拦截合法操作与防止全表误删。

#

31. MyBatis-Plus 的字段自动填充(MetaObjectHandler)

请说明 MyBatis-Plus 的字段自动填充(MetaObjectHandler)?

  • MetaObjectHandler 的作用
  • @TableField(fill=...) 自动填充
  • 创建/更新时间等场景

MyBatis-Plus 通过 MetaObjectHandler 实现字段自动填充,实体字段标注 @TableField(fill = FieldFill.INSERT / INSERT_UPDATE / UPDATE) 后,在插入或更新时自动填充该字段。实现 MetaObjectHandler 接口的 insertFill/updateFill 方法,可填充创建时间、更新时间、操作人等字段。填充发生在 SQL 注入前,自动为字段赋值,减少手工设置。适用于审计字段、公共字段的自动维护。

自动填充把"公共字段赋值"抽离为横切逻辑,通过 @TableField(fill) 与 MetaObjectHandler 配合。理解其触发时机(insert/update),可统一维护审计字段。

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
    }
}
#

32. MyBatis-Plus 的逻辑删除与全局配置

请说明 MyBatis-Plus 的逻辑删除与全局配置?

  • @TableLogic 逻辑删除
  • 全局逻辑删除配置
  • 删除与查询的自动改写

MyBatis-Plus 逻辑删除通过 @TableLogic 标注字段,删除时将逻辑删除标记为 1(UPDATE 而非 DELETE),查询时自动过滤已删除记录(WHERE deleted=0)。可通过全局配置(logic-delete-field、logic-delete-value、logic-not-delete-value)统一设置逻辑删除字段与值,避免每个实体标注。逻辑删除利于审计与恢复,但需注意唯一索引、关联查询与统计需考虑已删除数据。

逻辑删除是软删除,通过全局配置统一字段与值。理解其自动改写删除/查询,可正确设计软删除并规避唯一约束问题。