SpringBoot 配置多数据源

作者: 一曲畔上 | 来源:发表于2019-03-06 23:44 被阅读20次

    1,负载均衡和主从同步配置

    可以通过mysql的协议配置支持,不在本文探讨范围。配置方式如下

    jdbcUrl: jdbc:mysql:replication://host1:port1,host2:port2/dbname?useSSL=true&useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=true&serverTimezone=GMT%2B8
    

    2,分库分表等类的多数据源配置,不在本文探讨范围。

    3,其他使用多个不同业务数据源配置步骤如下:

    数据库连接池以c3p0为例,并且启用了手动式事务管理。

    3.1,配置数据库连接池类型

    spring: 
      datasource: 
        # 使用c3p0数据库连接池
        type: com.mchange.v2.c3p0.ComboPooledDataSource
    

    3.2,不使用系统默认数据库配置,手动配置两个数据源

    # 数据源配置
    datasource: 
      master: 
        driverClass: com.mysql.cj.jdbc.Driver
        jdbcUrl: jdbc:mysql:replication://localhost:3306/goods?useSSL=true&useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=true&serverTimezone=GMT%2B8
        user: demotest
        password: demotest
        minPoolSize: 4
        maxPoolSize: 20
        maxIdleTime: 1800000
        acquireIncrement: 2
        maxStatements: 0
        initialPoolSize: 4
        idleConnectionTestPeriod: 60
        acquireRetryAttempts: 5
        acquireRetryDelay: 1000
        breakAfterAcquireFailure: false
        testConnectionOnCheckin: true
        testConnectionOnCheckout: false
        preferredTestQuery: SELECT 1 FROM DUAL
      second: 
        driverClass: com.mysql.cj.jdbc.Driver
        jdbcUrl: jdbc:mysql:replication://localhost:3306/users?useSSL=true&useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8
        user: usertest
        password: usertest
        minPoolSize: 4
        maxPoolSize: 20
        maxIdleTime: 1800000
        acquireIncrement: 2
        maxStatements: 0
        initialPoolSize: 4
        idleConnectionTestPeriod: 60
        acquireRetryAttempts: 5
        acquireRetryDelay: 1000
        breakAfterAcquireFailure: false
        testConnectionOnCheckin: true
        testConnectionOnCheckout: false
        preferredTestQuery: SELECT 1 FROM DUAL
    

    3.3,配置两套MyBatis属性

    # mybatis配置
    mybatis: 
      master:
        config-location: classpath:bean/mybatis/master/mybatis_config.xml
        mapper-locations: classpath:/bean/mybatis/master/mapping/*.xml
        type-aliases-package: com.beyonds.phoenix.demo.domain.dao.master.po
        type-dao-package: com.beyonds.phoenix.demo.domain.dao.master
        executorType: REUSE
      second: 
        config-location: classpath:bean/mybatis/second/mybatis_config.xml
        mapper-locations: classpath:/bean/mybatis/second/mapping/*.xml
        type-aliases-package: com.beyonds.phoenix.demo.domain.dao.second.po
        type-dao-package: com.beyonds.phoenix.demo.domain.dao.second
        executorType: REUSE
    

    3.4,配置第一个数据源config文件

    @Configuration
    @MapperScan(basePackages = {"${mybatis.type-dao-package:com.beyonds.phoenix.demo.domain.dao.master}"}, 
                sqlSessionFactoryRef = "sqlSessionFactory")  
    @EnableTransactionManagement
    @ConditionalOnMissingBean({DataSourceConfiguration.class})
    @AutoConfigureOrder(-100)
    @AutoConfigureAfter({MybatisAutoConfiguration.class})
    public class DatasourceConfig {
        protected static Logger logger = LoggerFactory.getLogger("DAO.LOG");
        
        @Value("${spring.datasource.type}")
        private Class<? extends DataSource> datasourceType;
        
        /**
         * 定义服务模板
         * @param transactionTemplate 事务模板
         * @return 服务模板
         */
        @Bean(name = "wdServiceTemplate")
        public WdServiceTemplateImpl wdServiceTemplate(
                @Qualifier("transactionTemplate") TransactionTemplate transactionTemplate) {
            return new WdServiceTemplateImpl(transactionTemplate);
        }
        
        /**
         * 定义主数据源
         * @return 主数据源
         */
        @Bean(name = "dataSource", destroyMethod = "close")
        @Primary
        @ConfigurationProperties(prefix = "datasource.master")
        public DataSource dataSource() {
            return DataSourceBuilder.create().type(datasourceType).build();
        }
        
        /**
         * 定义事务管理器
         * @param dataSource 数据源
         * @return 事务管理器
         */
        @Bean(name = "transactionManager")
        public DataSourceTransactionManager transactionManager(@Qualifier("dataSource") DataSource dataSource) {
            return new DataSourceTransactionManager(dataSource);
        }
        
        /**
         * 定义事务模板
         * @param transactionManager 事务管理器
         * @return 事务模板
         * @throws Exception 异常
         */
        @Bean(name = "transactionTemplate")
        public TransactionTemplate transactionTemplate(
                @Qualifier("transactionManager") DataSourceTransactionManager transactionManager) 
                        throws Exception {
            DefaultTransactionDefinition defaultTransactionDefinition = 
                    new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED);
            defaultTransactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
            defaultTransactionDefinition.setTimeout(60); // 秒钟
            
            return new TransactionTemplate(transactionManager, defaultTransactionDefinition);
        }
        
        /**
         * +自定义数据源配置
         * @param dataSource dataSource
         * @param properties properties
         * @param resourceLoader resourceLoader
         * @param interceptorsProvider interceptorsProvider
         * @param databaseIdProviderContainer databaseIdProviderContainer
         * @param configurationCustomizersProvider configurationCustomizersProvider
         * @return configurationCustomizersProvider
         * @throws Exception Exception
         */
        @Bean(name = "sqlSessionFactory")
        public SqlSessionFactory sqlSessionFactory(
                @Qualifier("dataSource") DataSource dataSource,
                @Qualifier("mybatisPropertiesMaster") MybatisProperties properties,
                ResourceLoader resourceLoader,
                ObjectProvider<Interceptor[]> interceptorsProvider,
                ObjectProvider<DatabaseIdProvider> databaseIdProviderContainer,
                ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider
                ) throws Exception {
            SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
            factory.setDataSource(dataSource);
            factory.setVfs(SpringBootVFS.class);
            if (StringUtils.hasText(properties.getConfigLocation())) {
              factory.setConfigLocation(resourceLoader.getResource(properties.getConfigLocation()));
            }
            org.apache.ibatis.session.Configuration configuration = properties.getConfiguration();
            if (configuration == null && !StringUtils.hasText(properties.getConfigLocation())) {
              configuration = new org.apache.ibatis.session.Configuration();
            }
            List<ConfigurationCustomizer> configurationCustomizers = configurationCustomizersProvider.getIfAvailable();
            if (configuration != null && !CollectionUtils.isEmpty(configurationCustomizers)) {
              for (ConfigurationCustomizer customizer : configurationCustomizers) {
                customizer.customize(configuration);
              }
            }
            factory.setConfiguration(configuration);
            if (properties.getConfigurationProperties() != null) {
              factory.setConfigurationProperties(properties.getConfigurationProperties());
            }
            Interceptor[] interceptors = interceptorsProvider.getIfAvailable();
            if (!ObjectUtils.isEmpty(interceptors)) {
              factory.setPlugins(interceptors);
            }
            DatabaseIdProvider databaseIdProvider = databaseIdProviderContainer.getIfAvailable();
            if (databaseIdProvider != null) {
              factory.setDatabaseIdProvider(databaseIdProvider);
            }
            if (StringUtils.hasLength(properties.getTypeAliasesPackage())) {
              factory.setTypeAliasesPackage(properties.getTypeAliasesPackage());
            }
            if (StringUtils.hasLength(properties.getTypeHandlersPackage())) {
              factory.setTypeHandlersPackage(properties.getTypeHandlersPackage());
            }
            if (!ObjectUtils.isEmpty(properties.resolveMapperLocations())) {
              factory.setMapperLocations(properties.resolveMapperLocations());
            }
    
            return factory.getObject();
        }
        
        /**
         * +定义配置文件
         * @return MybatisProperties
         */
        @Bean(name = "mybatisPropertiesMaster")
        @ConfigurationProperties(prefix = "mybatis.master")
        public MybatisProperties mybatisProperties() {
            return new MybatisProperties();
        }
    }
    

    3.5,配置第二个数据源config文件

    @Configuration
    @MapperScan(basePackages = {"${mybatis.type-dao-package:com.beyonds.phoenix.demo.domain.dao.second}"}, 
                sqlSessionFactoryRef = "sqlSessionFactorySecond")  
    @EnableTransactionManagement
    @ConditionalOnMissingBean({DataSourceConfiguration.class})
    @AutoConfigureOrder(-90)
    @AutoConfigureAfter({MybatisAutoConfiguration.class})
    public class DatasourceSecondConfig {
        protected static Logger logger = LoggerFactory.getLogger("DAO.LOG");
        
        @Value("${spring.datasource.type}")
        private Class<? extends DataSource> datasourceType;
        
        /**
         * 定义服务模板
         * @param transactionTemplate 事务模板
         * @return 服务模板
         */
        @Bean(name = "wdServiceTemplateSecond")
        public WdServiceTemplateImpl wdServiceTemplateSecond(
                @Qualifier("transactionTemplateSecond") TransactionTemplate transactionTemplate) {
            return new WdServiceTemplateImpl(transactionTemplate);
        }
        
        /**
         * 定义主数据源
         * @return 主数据源
         */
        @Bean(name = "dataSourceSecond", destroyMethod = "close")
        @ConfigurationProperties(prefix = "datasource.second")
        public DataSource dataSourceSecond() {
            return DataSourceBuilder.create().type(datasourceType).build();
        }
        
        /**
         * 定义事务管理器
         * @param dataSource 数据源
         * @return 事务管理器
         */
        @Bean(name = "transactionManagerSecond")
        public DataSourceTransactionManager transactionManager(@Qualifier("dataSourceSecond") DataSource dataSource) {
            return new DataSourceTransactionManager(dataSource);
        }
        
        /**
         * 定义事务模板
         * @param transactionManager 事务管理器
         * @return 事务模板
         * @throws Exception 异常
         */
        @Bean(name = "transactionTemplateSecond")
        public TransactionTemplate transactionTemplate(
                @Qualifier("transactionManagerSecond") DataSourceTransactionManager transactionManager) 
                        throws Exception {
            DefaultTransactionDefinition defaultTransactionDefinition = 
                    new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED);
            defaultTransactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
            defaultTransactionDefinition.setTimeout(60); // 秒钟
            
            return new TransactionTemplate(transactionManager, defaultTransactionDefinition);
        }
        
        /**
         * +自定义数据源配置
         * @param dataSource dataSource
         * @param properties properties
         * @param resourceLoader resourceLoader
         * @param interceptorsProvider interceptorsProvider
         * @param databaseIdProviderContainer databaseIdProviderContainer
         * @param configurationCustomizersProvider configurationCustomizersProvider
         * @return configurationCustomizersProvider
         * @throws Exception Exception
         */
        @Bean(name = "sqlSessionFactorySecond")
        public SqlSessionFactory sqlSessionFactory(
                @Qualifier("dataSourceSecond") DataSource dataSource,
                @Qualifier("mybatisPropertiesSecond") MybatisProperties properties,
                ResourceLoader resourceLoader,
                ObjectProvider<Interceptor[]> interceptorsProvider,
                ObjectProvider<DatabaseIdProvider> databaseIdProviderContainer,
                ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider
                ) throws Exception {
            SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
            factory.setDataSource(dataSource);
            factory.setVfs(SpringBootVFS.class);
            if (StringUtils.hasText(properties.getConfigLocation())) {
              factory.setConfigLocation(resourceLoader.getResource(properties.getConfigLocation()));
            }
            org.apache.ibatis.session.Configuration configuration = properties.getConfiguration();
            if (configuration == null && !StringUtils.hasText(properties.getConfigLocation())) {
              configuration = new org.apache.ibatis.session.Configuration();
            }
            List<ConfigurationCustomizer> configurationCustomizers = configurationCustomizersProvider.getIfAvailable();
            if (configuration != null && !CollectionUtils.isEmpty(configurationCustomizers)) {
              for (ConfigurationCustomizer customizer : configurationCustomizers) {
                customizer.customize(configuration);
              }
            }
            factory.setConfiguration(configuration);
            if (properties.getConfigurationProperties() != null) {
              factory.setConfigurationProperties(properties.getConfigurationProperties());
            }
            Interceptor[] interceptors = interceptorsProvider.getIfAvailable();
            if (!ObjectUtils.isEmpty(interceptors)) {
              factory.setPlugins(interceptors);
            }
            DatabaseIdProvider databaseIdProvider = databaseIdProviderContainer.getIfAvailable();
            if (databaseIdProvider != null) {
              factory.setDatabaseIdProvider(databaseIdProvider);
            }
            if (StringUtils.hasLength(properties.getTypeAliasesPackage())) {
              factory.setTypeAliasesPackage(properties.getTypeAliasesPackage());
            }
            if (StringUtils.hasLength(properties.getTypeHandlersPackage())) {
              factory.setTypeHandlersPackage(properties.getTypeHandlersPackage());
            }
            if (!ObjectUtils.isEmpty(properties.resolveMapperLocations())) {
              factory.setMapperLocations(properties.resolveMapperLocations());
            }
    
            return factory.getObject();
        }
        
        /**
         * +定义配置文件
         * @return MybatisProperties
         */
        @Primary
        @Bean(name = "mybatisPropertiesSecond")
        @ConfigurationProperties(prefix = "mybatis.second")
        public MybatisProperties mybatisPropertiesSecond() {
            return new MybatisProperties();
        }
    }
    

    3.6,以上两步定义了两个不同的处理事务模板

    @Bean(name = "wdServiceTemplate")
    public WdServiceTemplateImpl wdServiceTemplate(
                @Qualifier("transactionTemplate") TransactionTemplate transactionTemplate) {
        return new WdServiceTemplateImpl(transactionTemplate);
    }
    

    @Bean(name = "wdServiceTemplateSecond")
    public WdServiceTemplateImpl wdServiceTemplate(
                @Qualifier("transactionTemplateSecond") TransactionTemplate transactionTemplate) {
        return new WdServiceTemplateImpl(transactionTemplate);
    }
    

    可供程序根据不同的业务场景选择使用不同的数据源。

    相关文章

      网友评论

        本文标题:SpringBoot 配置多数据源

        本文链接:https://www.haomeiwen.com/subject/dggfpqtx.html