Hello World

吞风吻雨葬落日 欺山赶海踏雪径

0%

MyBatis-Plus 分页插件失效问题排查与解决

问题描述

在使用 MyBatis-Plus 的分页功能时,发现分页插件失效,分页查询无法正常工作,每次查询都返回全部数据。

问题背景

项目采用多数据源架构:

  • 主数据源:MySQL,使用 MysqlConfig 配置类
  • 从数据源:StarRocks,使用 StarRocksConfig 配置类

两个配置类中都各自定义了 SqlSessionFactory Bean。

根本原因

自动配置失效机制

当项目中手动定义SqlSessionFactory Bean 时,Spring Boot 的自动配置机制会退让(auto-configuration backoff),导致 MyBatis-Plus 的自动配置类 MybatisPlusAutoConfiguration 不再生效。

具体分析

  1. MysqlConfig.java 中手动创建了 sqlSessionFactory

    1
    2
    3
    4
    5
    6
    7
    8
    @Primary
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
    MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/**/*.xml"));
    return bean.getObject();
    }
  2. StarRocksConfig.java 中也手动创建了 starrocksSqlSessionFactory

    1
    2
    3
    4
    5
    6
    7
    @Bean(name = "starrocksSqlSessionFactory")
    public SqlSessionFactory starrocksSqlSessionFactory(@Qualifier("starrocksDataSource") DataSource dataSource) throws Exception {
    MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:smapper/**/*.xml"));
    return bean.getObject();
    }
  3. 由于手动创建了 SqlSessionFactory,原本通过 @Bean 方式定义的 PaginationInterceptor 无法被自动注入:

    1
    2
    3
    4
    5
    6
    // 原注释掉的代码,自动注入失效
    // @Bean
    // public PaginationInterceptor paginationInterceptor() {
    // PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
    // return paginationInterceptor;
    // }

解决方案

在手动创建 SqlSessionFactory 时,显式调用 setPlugins() 方法设置分页插件:

1
2
3
4
5
6
7
8
9
10
@Primary
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/**/*.xml"));
// 手动设置分页插件
bean.setPlugins(new PaginationInterceptor());
return bean.getObject();
}

关键要点

多数据源场景下的 MyBatis-Plus 配置

场景 配置方式 分页插件生效方式
单数据源 + 自动配置 使用 Spring Boot 自动配置 @Bean PaginationInterceptor 自动注入
单数据源 + 手动配置 手动创建 SqlSessionFactory 需要手动 setPlugins()
多数据源 手动创建多个 SqlSessionFactory 每个都需要手动 setPlugins()

最佳实践

  1. 多数据源场景:每个 SqlSessionFactory 都需要显式设置插件

    1
    2
    3
    4
    5
    // 主数据源
    bean.setPlugins(new PaginationInterceptor());

    // 从数据源(如果需要分页功能)
    bean.setPlugins(new PaginationInterceptor());
  2. 插件链:如果需要多个插件,可以使用数组

    1
    2
    3
    4
    bean.setPlugins(new Interceptor[]{
    new PaginationInterceptor(),
    // 其他 MyBatis 插件...
    });
  3. 条件配置:StarRocks 作为分析型数据库,通常不需要分页功能,可以不设置分页插件

经验总结

  • 理解自动配置的退让机制:手动定义 Bean 会导致相关自动配置失效
  • 多数据源配置要全面:每个数据源的配置类都需要独立配置完整的 MyBatis 功能
  • 调试技巧:当自动配置失效时,检查是否有手动创建的同名或同类型 Bean
  • 文档优先:涉及框架核心功能的修改,应当及时记录文档