【问题标题】:Dynamic Datasource using SpringBoot [duplicate]使用 SpringBoot 的动态数据源 [重复]
【发布时间】:2019-12-05 01:47:34
【问题描述】:

我正在使用 SpringBoot 编写一个微服务,并且我需要动态选择数据源。我将根据参数选择数据源。每个数据源将指向具有相同架构(相同的表、触发器、存储过程等)的 Oracle 数据库。我该如何实现这个要求?

【问题讨论】:

    标签: java spring-boot dynamic datasource


    【解决方案1】:

    在 springboot 中试试这个 AbstractRoutingDataSource。

    https://spring.io/blog/2007/01/23/dynamic-datasource-routing/

    【讨论】:

      【解决方案2】:

      您必须在 application.properties 中实现两个配置数据源,然后配置两个 EntityManagerFactory 和 TransactionManager。您可以使用不同的存储库在两个数据源之间切换。

      application.properties

      first.datasource.url=jdbc:oracle:thin:@//host:1521/firstdb
      first.datasource.username=first
      first.datasource.password=first
      first.datasource.driver-class-name=oracle.jdbc.OracleDriver
      
      second.datasource.url=jdbc:oracle:thin:@//host:1521/firstdb
      second.datasource.username=second
      second.datasource.password=second
      second.datasource.driver-class-name=oracle.jdbc.OracleDriver
      
      spring.jpa.database=default
      

      每个实体和存储库有两个包,需要设置两个配置。

      第一:

      @Configuration
      @EnableTransactionManagement
      @EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactory",
        basePackages = { "com.system.first.repo" }
      )
      public class FirstDbConfig {
      
        @Primary
        @Bean(name = "dataSource")
        @ConfigurationProperties(prefix = "first.datasource")
        public DataSource dataSource() {
          return DataSourceBuilder.create().build();
        }
      
        @Primary
        @Bean(name = "entityManagerFactory")
        public LocalContainerEntityManagerFactoryBean 
        entityManagerFactory(
          EntityManagerFactoryBuilder builder,
          @Qualifier("dataSource") DataSource dataSource
        ) {
          return builder
            .dataSource(dataSource)
            .packages("com.system.first.domain")
            .persistenceUnit("first")
            .build();
        }
      
        @Primary
        @Bean(name = "transactionManager")
        public PlatformTransactionManager transactionManager(
          @Qualifier("entityManagerFactory") EntityManagerFactory 
          entityManagerFactory
        ) {
          return new JpaTransactionManager(entityManagerFactory);
        }
      }
      

      第二:

      @Configuration
      @EnableTransactionManagement
      @EnableJpaRepositories(
        entityManagerFactoryRef = "secondEntityManagerFactory",
        transactionManagerRef = "secondTransactionManager",
        basePackages = { "com.system.second.repo" }
      )
      public class SecondDbConfig {
      
        @Bean(name = "secondDataSource")
        @ConfigurationProperties(prefix = "second.datasource")
        public DataSource dataSource() {
          return DataSourceBuilder.create().build();
        }
      
        @Bean(name = "secondEntityManagerFactory")
        public LocalContainerEntityManagerFactoryBean 
        secondEntityManagerFactory(
          EntityManagerFactoryBuilder builder,
          @Qualifier("secondDataSource") DataSource dataSource
        ) {
          return
            builder
              .dataSource(dataSource)
              .packages("com.system.second.domain")
              .persistenceUnit("second")
              .build();
        }
        @Bean(name = "secondTransactionManager")
        public PlatformTransactionManager secondTransactionManager(
          @Qualifier("secondEntityManagerFactory") EntityManagerFactory
          secondEntityManagerFactory
        ) {
          return new JpaTransactionManager(secondEntityManagerFactory);
        }
      }
      

      【讨论】:

        【解决方案3】:

        在启动时配置所有数据源,然后:

        要么:

        一个。有一个不同的 repo 类来实现每个数据源,在调用相应的 repo 之前检查参数。

        b.拥有一个检查参数并使用相应数据源进行查询的 repo 类。

        【讨论】:

          【解决方案4】:

          我确实实现了类似的东西......

          我使用 application.properties 来存储数据源连接

          Datasource drive name
          spring.datasource.driver-class-name=
          spring.datasource.url=
          spring.datasource.username=
          spring.datasource.password=
          

          有一些关于如何读取和写入属性的代码示例

          https://github.com/evandbrown/amediamanager/blob/d42228a924cfbf14832e774a77c03eb0e9c2dba1/src/main/java/com/amediamanager/config/ConfigurationProviderChain.java

          创建一个端点来更新你的属性

          @PutMapping("/update")
              public ResponseEntity<?> updateConnection(@RequestBody final List<ConfigurationProperty> properies) {
                  LOGGER.trace("Updating data source properties ");
                  for (final ConfigurationProperty configurationProperty : properies) {
                      config.getConfigurationProvider().persistDatabaseProperty(configurationProperty.getPropertyName(),
                              configurationProperty.getPropertyValue());
                  }
          
                      }
                  }
                  return new ResponseEntity<> (HttpStatus.OK);
              }
          

          另一个经验提示,在执行更新端点之前 ping 连接。 :) 我的实现的唯一结论是,用户需要重新启动服务器才能对拾取进行更改。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-05-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-03-20
            • 2015-09-05
            • 2022-12-17
            相关资源
            最近更新 更多