【问题标题】:Spring boot - how to configure multiple datasourcesSpring boot - 如何配置多个数据源
【发布时间】:2015-07-03 06:42:50
【问题描述】:

我正在尝试使用 Spring Boot 设置多个数据源(MySql、Postgres 和 Oracle)。我没有使用 JPA。使用 JdbcTemplate 进行设置。

我试过设置这样的东西。

application.properties

spring.datasource.test-oracle.username=test-oracle
spring.datasource.test-oracle.password=test-password
spring.datasource.test-oracle.url=dburl/test
spring.datasource.test-oracle.driver-class-name=oracle.jdbc.OracleDriver

spring.datasource.int-oracle.username=int-oracle
spring.datasource.int-oracle.password=int-password
spring.datasource.int-oracle.url=dburl/int
spring.datasource.int-oracle.driver-class-name=oracle.jdbc.driver.OracleDriver

spring.datasource.d.int-mysql.username=user
spring.datasource.d.int-mysql.password=password
spring.datasource.d.int-mysql.url=dburl/d
spring.datasource.d.int-mysql.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.m.int-mysql.username=user
spring.datasource.m.int-mysql.password=password
spring.datasource.m.int-mysql.url=dburl/m
spring.datasource.m.int-mysql.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.d.test-mysql.username=user
spring.datasource.d.test-mysql.password=password
spring.datasource.d.test-mysql.url=dburl/d
spring.datasource.d.test-mysql.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.m.test-mysql.username=user
spring.datasource.m.test-mysql.password=password
spring.datasource.m.test-mysql.url=dburl/m
spring.datasource.m.test-mysql.driver-class-name=com.mysql.jdbc.Driver

MySqlConfiguration.java

@Configuration
public class MySqlConfiguration() {

   @Bean(name = "dMySql")
   @ConfigurationProperties(prefix = "spring.datasource.d.int-mysql")
   public DataSource mysqlDrupalDataSource() {
     return DataSourceBuilder.create().build();
   }

   @Bean(name = "dJdbc")
   public JdbcTemplate drupalJdbcTemplate(DataSource dMySql) {
      return new JdbcTemplate(dMySql);
   }

   @Bean(name = "mMySql")
   @ConfigurationProperties(prefix = "spring.datasource.m.int-mysql")
   public DataSource mysqlDrupalDataSource() {
      return DataSourceBuilder.create().build();
   }

   @Bean(name = "mJdbc")
   public JdbcTemplate drupalJdbcTemplate(DataSource mMySql) {
      return new JdbcTemplate(mMySql);
   }
}

OracleConfiguration.java

@Configuration
public class OracleConfiguration {

   @Primary
   @Bean(name = "tOracle")
   @ConfigurationProperties(prefix = "spring.datasource.test-oracle")
   public DataSource heOracleDataSource() {
      return DataSourceBuilder.create().build();
   }

   @Bean(name = "tOracleJdbc")
   public JdbcTemplate jdbcTemplate(DataSource tOracle) {
      return new JdbcTemplate(tOracle);
   }

   @Bean(name = "iOracle")
   @ConfigurationProperties(prefix = "spring.datasource.int-oracle")
   public DataSource heOracleDataSource() {
      return DataSourceBuilder.create().build();
   }

   @Bean(name = "iOracleJdbc")
   public JdbcTemplate jdbcTemplate(DataSource iOracle) {
      return new JdbcTemplate(iOracle);
   }
}

我不确定以上是否是解决此问题的正确方法。当我按照引导文档使用@Primary 时,始终使用具有@Primary 的Bean。然后我像这样在我的 DAO 实现中使用配置

DAO 实现之一

@Repository
public class DAOImpl implements DAOInterface {

    @Autowired
    @Qualifier("dJdbc")
    private JdbcTemplate jdbc;

    @Override
    public Map<String, Object> getBasicStudentInfo(String MAIL) {
        return jdbc.queryForMap(GET_BASIC_STUDENT_INFO, new Object[]{MAIL});
}

我该怎么做呢?我确实看过很多关于多个数据源的文章,但不幸的是,这些示例或解决方案不适合我。

除此之外,我还需要能够根据一些用户输入查询数据库。因此,如果用户提供环境,例如“test”或“int”,我如何根据该输入触发正确的属性。

我知道 Environment 是 @Autowired 到 Spring boot 中的,我可以拦截用户输入,但不确定我应该如何在用户输入和 DAO 配置之间提供管道。

如果有什么不清楚的地方,或者我需要更多的解释,或者需要更多的代码,我可以提供。任何帮助解决这种情况将不胜感激。谢谢

【问题讨论】:

    标签: java spring-boot jdbctemplate


    【解决方案1】:

    这里是您问题的完整解决方案...

    您的配置类将如下所示:

    MySqlConfiguration.java

    @Configuration
    public class MySqlConfiguration {
    
       @Bean(name = "dMySql")
       @ConfigurationProperties(prefix = "spring.datasource.d.int-mysql")
       public DataSource mysqlDrupalDataSource() {
         return DataSourceBuilder.create().build();
       }
    
       @Bean(name = "dJdbc")
       public JdbcTemplate drupalJdbcTemplate(@Qualifier("dMySql") DataSource dMySql) {
          return new JdbcTemplate(dMySql);
       }
    
       @Bean(name = "mMySql")
       @ConfigurationProperties(prefix = "spring.datasource.m.int-mysql")
       public DataSource mysqlDrupalDataSource() {
          return DataSourceBuilder.create().build();
       }
    
       @Bean(name = "mJdbc")
       public JdbcTemplate drupalJdbcTemplate(@Qualifier("mMySql") DataSource mMySql) {
          return new JdbcTemplate(mMySql);
       }
    }
    

    OracleConfiguration.java

    @Configuration
    public class OracleConfiguration {
    
       @Primary
       @Bean(name = "tOracle")
       @ConfigurationProperties(prefix = "spring.datasource.test-oracle")
       public DataSource heOracleDataSource() {
          return DataSourceBuilder.create().build();
       }
    
       @Bean(name = "tOracleJdbc")
       public JdbcTemplate jdbcTemplate(@Qualifier("tOracle") DataSource tOracle) {
          return new JdbcTemplate(tOracle);
       }
    
       @Bean(name = "iOracle")
       @ConfigurationProperties(prefix = "spring.datasource.int-oracle")
       public DataSource heOracleDataSource() {
          return DataSourceBuilder.create().build();
       }
    
       @Bean(name = "iOracleJdbc")
       public JdbcTemplate jdbcTemplate(@Qualifier("iOracle") DataSource iOracle) {
          return new JdbcTemplate(iOracle);
       }
    }
    

    在您的 DAO 类中,您可以像这样自动装配 JdbcTemplate:

    @Repository
    public class DAOImpl implements DAOInterface {
    
        @Autowired
        @Qualifier("dJdbc")
        private JdbcTemplate dJdbc;
    
        @Autowired
        @Qualifier("mJdbc")
        private JdbcTemplate mJdbc;
    
        @Autowired
        @Qualifier("tOracleJdbc")
        private JdbcTemplate tOracleJdbc;
    
        @Autowired
        @Qualifier("iOracleJdbc")
        private JdbcTemplate iOracleJdbc;
    
        @Override
        public Map<String, Object> getBasicStudentInfo(String MAIL) {
            return dJdbc.queryForMap(GET_BASIC_STUDENT_INFO, new Object[]{MAIL});
        }
    
        .
        .
        .
    }
    

    注意:确保使用 @Primary 注释对 DataSource 之一进行注释

    【讨论】:

    • 我会注意到我在将 DataSources 与 JdbcTemplates 和 DataSources 与 JdbcTemplates 混合时遇到了麻烦。我发现最好遵循这个示例,其中每个 DataSource 都在配置文件中定义了其 JdbcTemplate。
    • @Shrikant Salgar 正在使用 spring boot 2.0 这些是我的 application.properties 详细信息 spring.datasource-app.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver spring.datasource-app。 url=xxxx 但由于 driverClassName 需要 jdbcUrl 而出现错误
    • @VikasKalapur Spring 2.0 默认使用 HikariCP 数据源,它需要 jdbc-url 配置参数名称。因此,将您的配置更改为 spring.datasource-app.jdbc-url=xxxx 并尝试。
    【解决方案2】:

    我的设置:spring-boot 版本 1.2.5.RELEASE

    我成功地运行了这样的设置,通过在每个 JDBC 方法创建中添加 @Qualifier 来使用正确的数据源创建 jdbc

    因此,对于每个 JDBC 方法,您都应该像这样匹配符合条件的数据源

    @Bean(name = "dJdbc")
    public JdbcTemplate drupalJdbcTemplate(@Qualifier("dMySql") DataSource dMySql) {
        return new JdbcTemplate(dMySql);
    }
    

    无论您为 @Primary 选择什么,对每个 JDBC 使用 @Qualifier 都应该可以正常工作。 在存储库中自动装配 jdbcTemplates,并为它们使用 @Qualifier 也可以。

    【讨论】:

      【解决方案3】:

      在您的 DAO 中,您可以连接额外的 jdbctemplates。然后在运行时你可以选择使用哪一个。

      @Repository
      public class DAOImpl implements DAOInterface {
      
      @Autowired
      @Qualifier("tOracle")
      private JdbcTemplate testJdbc;
      
      @Autowired
      @Qualifier("intOracle")
      private JdbcTemplate intJdbc;
      
      @Override
      public Map<String, Object> getBasicStudentInfo(String MAIL, String source) {
          if ("TEST".equals(source)){
                return testJdbc.queryForMap(GET_BASIC_STUDENT_INFO, new Object[]{MAIL});
          }else {
                return intJdbc.queryForMap(GET_BASIC_STUDENT_INFO, new Object[]{MAIL});       
          }
      }
      

      【讨论】: