Mapper icon indicating copy to clipboard operation
Mapper copied to clipboard

SpringBoot + Mybatis + 通用 Mapper 如何配置多数据源?

Open william-abel opened this issue 5 years ago • 2 comments

SpringBoot + Mybatis + 通用 Mapper 如何配置多数据源? 我始终配置不成功 有没有实例项目

william-abel avatar May 10 '20 05:05 william-abel

创建完DataSource以后,关键是doScan方法,让dataSouce扫描对应的Mapper。 这种方式可以实现的多种情况:

  1. 不同的表对应不同的数据源
  2. 相同的表对应不同的数据源
@Configuration
public class SqlSessionFactoryConfiguration implements ResourceLoaderAware, EnvironmentAware, BeanFactoryPostProcessor {
    private static final Logger log = LogManager.getLogger(SqlSessionFactoryConfiguration.class);
    private Environment environment;
    private ResourceLoader resourceLoader;

    public SqlSessionFactoryConfiguration() {
    }

    private void doScan(BeanDefinitionRegistry registry, String sqlStringFactory, String... basePackage) {
        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
        scanner.setMapperProperties(this.environment);
        scanner.setSqlSessionFactoryBeanName(sqlStringFactory);
        scanner.setResourceLoader(this.resourceLoader);
        scanner.registerFilters();
        scanner.doScan(basePackage);
    }

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
            SqlSessionFactoryProperties sqlSessionFactoryProperties = (SqlSessionFactoryProperties)SpringBootBindUtil.bind(this.environment, SqlSessionFactoryProperties.class, "jdbc");
            Map<String, DatasourceConfiguration> configuration = sqlSessionFactoryProperties.getConfig();
            if (configuration != null) {
                MybatisProperties mybatisProperties = (MybatisProperties)SpringBootBindUtil.bind(this.environment, MybatisProperties.class, "mybatis");
                DefaultListableBeanFactory register = (DefaultListableBeanFactory)beanFactory;
                BeanDefiner beanDefiner = new BeanDefiner(register);
                configuration.forEach((k, v) -> {
                    Assert.notEmpty(v.getDataSource(), "datasource shall not be null");
                    Assert.notEmpty(v.getBasePackages(), "basePackages shall not be null");
                    Assert.hasLength(v.getDefaultClusterName(), "clusterName shall not be null");
                    DynamicRoutingDataSource dynamicRoutingDataSource = DataSourceFactory.createDynamicRoutingDataSource(v.getDefaultClusterName(), v.getDataSource());
                    beanDefiner.registerDataSource(k, dynamicRoutingDataSource);
                    String transactionManagerBeanName = beanDefiner.registerTransactionManager(k, this.transactionManager(dynamicRoutingDataSource));
                    if (v.getTransactionServicePackages() != null) {
                        String[] var8 = v.getTransactionServicePackages();
                        int var9 = var8.length;

                        for(int var10 = 0; var10 < var9; ++var10) {
                            String packageName = var8[var10];
                            log.debug("register transaction manager name:{},{}", packageName, transactionManagerBeanName);
                            CustomizedTransactionInterceptor.putTransactionManagerName(packageName, transactionManagerBeanName);
                        }
                    }

                    SqlSessionFactory sqlSessionFactory = this.sqlSessionFactory(k, dynamicRoutingDataSource, mybatisProperties);
                    String factory = beanDefiner.registerSqlSessionFactory(k, sqlSessionFactory);
                    beanDefiner.registerSqlSessionTemplate(k, this.sqlSessionTemplate(sqlSessionFactory));
                    this.doScan(register, factory, v.getBasePackages());
                });
                BeanFactoryTransactionAttributeSourceAdvisor advisor = (BeanFactoryTransactionAttributeSourceAdvisor)register.getBean(BeanFactoryTransactionAttributeSourceAdvisor.class);
                CustomizedTransactionInterceptor interceptor = new CustomizedTransactionInterceptor();
                register.registerBeanDefinition("transactionInterceptor", BeanDefinitionBuilder.genericBeanDefinition(CustomizedTransactionInterceptor.class, () -> {
                    return interceptor;
                }).setRole(2).getBeanDefinition());
                interceptor.setTransactionAttributeSource((TransactionAttributeSource)register.getBean(TransactionAttributeSource.class));
                advisor.setAdvice(interceptor);
            }

        } catch (BeansException var9) {
            log.error("catch Exception {} while initiate sqlSessionFactory", var9.getLocalizedMessage(), var9);
            throw var9;
        } catch (Exception var10) {
            log.error("catch Exception {} while initiate sqlSessionFactory", var10.getLocalizedMessage(), var10);
            throw new BeanCreationException("initiate error " + var10.getLocalizedMessage(), var10);
        }
    }

    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    private SqlSessionFactory sqlSessionFactory(String k, DataSource dataSource, MybatisProperties properties) {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        factory.setVfs(SpringBootVFS.class);
        if (StringUtils.hasText(properties.getConfigLocation())) {
            factory.setConfigLocation(this.resourceLoader.getResource(properties.getConfigLocation()));
        }

        Properties configurationProperties = properties.getConfigurationProperties();
        if (configurationProperties != null) {
            factory.setConfigurationProperties(configurationProperties);
        }

        String typeAliasesPackage = properties.getTypeAliasesPackage();
        if (StringUtils.hasLength(typeAliasesPackage)) {
            factory.setTypeAliasesPackage(typeAliasesPackage);
        }

        if (properties.getTypeAliasesSuperType() != null) {
            factory.setTypeAliasesSuperType(properties.getTypeAliasesSuperType());
        }

        if (StringUtils.hasLength(properties.getTypeHandlersPackage())) {
            factory.setTypeHandlersPackage(properties.getTypeHandlersPackage());
        }

        if (!ObjectUtils.isEmpty(properties.resolveMapperLocations())) {
            factory.setMapperLocations(properties.resolveMapperLocations());
        }

        try {
            return factory.getObject();
        } catch (Exception var8) {
            throw new RuntimeException(var8);
        }
    }

    private SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
        return sqlSessionTemplate;
    }

    private DataSourceTransactionManager transactionManager(DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
        return transactionManager;
    }
}

maheng-hub avatar May 19 '20 12:05 maheng-hub

师兄,可否提供具体的demo,供参考

253286440

sukai-cheng avatar Apr 09 '22 01:04 sukai-cheng