You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免Mybatis为每个SqlSessionTemplate重复加载配置?

解决多分片场景下Mybatis重复加载配置导致初始化慢的问题

针对Spring 4.3 + Mybatis 3.4 + Mybatis-spring 1.3环境下,多分片每个SqlSessionTemplate重复加载配置和映射器导致初始化耗时过长的问题,可以通过预加载基础Configuration并克隆复用的方式解决,核心思路是先加载一次配置和映射器,再为每个分片克隆独立的Configuration并绑定对应数据源,避免重复加载。

实现步骤

1. 预加载基础Configuration(仅加载配置与映射器,不绑定业务数据源)

先创建一个基础的SqlSessionFactoryBean,仅加载Mybatis核心配置和映射器文件,设置临时数据源避免初始化报错,获取已加载完成的Configuration作为复用模板。

// 初始化基础SqlSessionFactoryBean,仅加载配置和映射器
SqlSessionFactoryBean baseFactoryBean = new SqlSessionFactoryBean();
baseFactoryBean.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
baseFactoryBean.setMapperLocations(
    new PathMatchingResourcePatternResolver().getResources("classpath:mappers/*.xml")
);
// 设置临时内存数据源,仅用于完成Configuration初始化
baseFactoryBean.setDataSource(new DriverManagerDataSource("jdbc:h2:mem:tmp", "sa", ""));

// 获取已加载完所有配置和映射器的基础Configuration
Configuration baseConfig = baseFactoryBean.getObject().getConfiguration();

2. 为每个分片克隆Configuration并绑定对应数据源

针对每个分片的独立数据源,克隆基础Configuration,替换其Environment中的数据源,再创建专属的SqlSessionFactory和SqlSessionTemplate,无需重复加载配置与映射器。

方式一:手动复制核心配置(可控性强)

// 遍历所有分片数据源
for (DataSource shardDataSource : shardDataSources) {
    // 基于基础配置的环境模板,创建绑定当前分片数据源的新Environment
    Environment newEnv = new Environment(
        baseConfig.getEnvironment().getId(),
        baseConfig.getEnvironment().getTransactionFactory(),
        shardDataSource
    );
    Configuration clonedConfig = new Configuration(newEnv);
    
    // 复制基础Configuration的核心配置项
    clonedConfig.setCacheEnabled(baseConfig.isCacheEnabled());
    clonedConfig.setLazyLoadingEnabled(baseConfig.isLazyLoadingEnabled());
    clonedConfig.setAggressiveLazyLoading(baseConfig.isAggressiveLazyLoading());
    // 按需复制其他配置项(如日志实现、类型处理器等)
    
    // 复用已加载的映射器,避免重新解析XML文件
    for (Class<?> mapperInterface : baseConfig.getMapperRegistry().getMappers()) {
        clonedConfig.addMapper(mapperInterface);
    }
    
    // 创建当前分片的SqlSessionFactory与SqlSessionTemplate
    SqlSessionFactoryBean shardFactoryBean = new SqlSessionFactoryBean();
    shardFactoryBean.setConfiguration(clonedConfig);
    // 无需重复设置configLocation和mapperLocations
    SqlSessionFactory shardSessionFactory = shardFactoryBean.getObject();
    SqlSessionTemplate shardTemplate = new SqlSessionTemplate(shardSessionFactory);
    
    // 将分片SqlSessionTemplate注册到Spring容器或路由封装器中
}

方式二:使用BeanUtils快速复制(简化代码)

// 遍历所有分片数据源
for (DataSource shardDataSource : shardDataSources) {
    // 克隆基础Configuration实例
    Configuration clonedConfig = new Configuration();
    // 复制基础配置的所有属性(包括已加载的映射器、配置项)
    org.springframework.beans.BeanUtils.copyProperties(baseConfig, clonedConfig);
    
    // 替换Environment中的数据源为当前分片数据源
    Environment newEnv = new Environment(
        baseConfig.getEnvironment().getId(),
        baseConfig.getEnvironment().getTransactionFactory(),
        shardDataSource
    );
    clonedConfig.setEnvironment(newEnv);
    
    // 创建分片专属的SqlSessionFactory与SqlSessionTemplate
    SqlSessionFactoryBean shardFactoryBean = new SqlSessionFactoryBean();
    shardFactoryBean.setConfiguration(clonedConfig);
    SqlSessionFactory shardSessionFactory = shardFactoryBean.getObject();
    SqlSessionTemplate shardTemplate = new SqlSessionTemplate(shardSessionFactory);
    
    // 注册到容器或路由封装器
}

关键注意事项

  • 必须使用独立Configuration实例:每个分片对应单独的Configuration,绝对不能共享实例,否则会出现数据源串用的问题。
  • 复用已加载的映射器:基础Configuration已经完成了映射器的解析与注册,克隆后直接复用即可,彻底避免重复解析XML的耗时。
  • 临时数据源不影响业务:预加载时使用的临时内存数据源仅用于完成Configuration初始化,不会参与任何业务数据库操作。

内容的提问来源于stack exchange,提问作者rooot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 05:47:32