如何在 Spring Boot 中将 HikariCP 与两个数据源结合使用 Flyway

Posted

技术标签:

【中文标题】如何在 Spring Boot 中将 HikariCP 与两个数据源结合使用 Flyway【英文标题】:How to use HikariCP in Spring Boot with two datasources in conjunction with Flyway 【发布时间】:2017-11-06 11:27:36 【问题描述】:

我想在我的 Spring 启动应用程序中使用 HikariCP 作为 JDBC 连接池。我有两个数据源(mysql 数据库作为主数据库并通过 Hibernate 访问这些数据,另外还有一个 Oracle 数据库用于通过 JDBCTemplate 读取其他数据)。

我将 MySQL 数据源设置为主 bean:

@Bean
@Primary
@ConfigurationProperties("spring.datasource")
public DataSourceProperties mySQLDataSourceProperties() 
    return new DataSourceProperties();



@Bean
@Primary
@ConfigurationProperties("spring.datasource")
public DataSource mySQLDataSource() 
    return mySQLDataSourceProperties().initializeDataSourceBuilder().build();


@Bean
@ConfigurationProperties("oracle.datasource")
public DataSourceProperties oracleDataSourceProperties() 
    return new DataSourceProperties();


@Bean(name = "oracleDatabase")
@ConfigurationProperties("oracle.datasource")
public DataSource oracleDataSource() 
    return oracleDataSourceProperties().initializeDataSourceBuilder().build();


 @Bean
 public JdbcTemplate oracleJdbcTemplate(@Qualifier("oracleDatabase") DataSource oracleDb) 
     return new JdbcTemplate(oracleDb);
 

我将以下配置放在我的 application.properties 中:

spring.datasource.type=com.zaxxer.hikari.HikariDataSource

spring.datasource.hikari.minimum-idle=7
spring.datasource.hikari.pool-name=Test-1

spring.datasource.hikari.data-source-properties.prepStmtCacheSize=250
spring.datasource.hikari.data-source-properties.prepStmtCacheSqlLimit=2048
spring.datasource.hikari.data-source-properties.cachePrepStmts=true
spring.datasource.hikari.data-source-properties.useServerPrepStmts=true

不幸的是,这些 HikariCP 配置没有被读取:

 HikariConfig - dataSourceJNDI..................none
 HikariConfig - dataSourceProperties............password=<masked>
 HikariConfig - driverClassName................."com.mysql.jdbc.Driver"
 HikariConfig - healthCheckProperties...........
 HikariConfig - healthCheckRegistry.............none
 HikariConfig - idleTimeout.....................600000
 HikariConfig - initializationFailFast..........true
 HikariConfig - initializationFailTimeout.......1
 HikariConfig - isolateInternalQueries..........false
 HikariConfig - jdbc4ConnectionTest.............false
 HikariConfig - jdbcUrl........................."jdbc:mysql://localhost:3306/testDB"
 HikariConfig - leakDetectionThreshold..........0
 HikariConfig - maxLifetime.....................1800000
 HikariConfig - maximumPoolSize.................10
 HikariConfig - metricRegistry..................none
 HikariConfig - metricsTrackerFactory...........none
 HikariConfig - minimumIdle.....................10
 HikariConfig - password........................<masked>
 HikariConfig - poolName........................"HikariPool-1"

创建 HikariCP bean 并停用 DataSource 自动配置并删除“spring.datasource”:

@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)
@SpringBootApplication
@ComponentScan
public class SpringApplication 


@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.hikari")
public HikariConfig hikariConfig() 
    return new HikariConfig();


@Bean
public DataSource dataSource() 
    return new HikariDataSource(hikariConfig());

解决了我的问题:

 HikariConfig - dataSourceJNDI..................none
 HikariConfig - dataSourceProperties............password=<masked>, prepStmtCacheSqlLimit=2048, cachePrepStmts=true, useServerPrepStmts=true, prepStmtCacheSize=250
 HikariConfig - driverClassName................."com.mysql.jdbc.Driver"
 HikariConfig - healthCheckProperties...........
 HikariConfig - healthCheckRegistry.............none
 HikariConfig - idleTimeout.....................600000
 HikariConfig - initializationFailFast..........true
 HikariConfig - initializationFailTimeout.......1
 HikariConfig - isolateInternalQueries..........false
 HikariConfig - jdbc4ConnectionTest.............false
 HikariConfig - jdbcUrl........................."jdbc:mysql://localhost:3306/testDB?autoReconnect=true"
 HikariConfig - leakDetectionThreshold..........0
 HikariConfig - maxLifetime.....................1800000
 HikariConfig - poolName........................"Test-1"

但随后 Flyway 显示了一些以前未显示的奇怪警告,我必须在运行 Spring 应用程序之前手动创建数据库架构,即:创建架构不再起作用。

[WARN ] JdbcTemplate - DB: Can't create database 'test'; database exists (SQL State: HY000 - Error Code: 1007)
[WARN ] JdbcTemplate - DB: Unknown table 'testSchema.tenant' (SQL State: 42S02 - Error Code: 1051)
[WARN ] JdbcTemplate - DB: Unknown table 'testSchema.user' (SQL State: 42S02 - Error Code: 1051) 

我的 Flyway SQL 脚本是纯 DDL 脚本:

CREATE SCHEMA IF NOT EXISTS `testSchema` DEFAULT CHARACTER SET utf8 ;

DROP TABLE IF EXISTS `testSchema`.`tenant`;

CREATE TABLE `testSchema`.`tenant` (
  `id` int NOT NULL AUTO_INCREMENT,

我认为禁用自动数据源配置不是最好的解决方案,因为 Flyway 停止创建架构并显示警告。有没有其他方法可以解决这个问题?

【问题讨论】:

【参考方案1】:

声明你自己的DataSource 已经隐式禁用了 Spring Boot 的数据源自动配置。换句话说,这不会产生任何影响:

@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class)

我认为问题在于您没有将 Hikari 特定配置绑定到您的 MySQL DataSource。你需要做这样的事情:

@Bean
@Primary
@ConfigurationProperties("spring.datasource.hikari")
public DataSource mySQLDataSource() 
    return mySQLDataSourceProperties().initializeDataSourceBuilder().build();

这意味着您的mySQLDataSourceProperties 配置了通用数据源配置。然后他们创建一个HikariDataSource,进一步配置了 Hikari 特定的配置。

【讨论】:

能否请您在这里指导我:***.com/questions/62510899/…? 很好的答案,感谢您在 Spring Boot/REST 上所做的工作。您是否有机会提供一个指向 Spring Boot 中记录的链接?【参考方案2】:

感谢 Andy 快速而有价值的回答!你让我走上正轨。在摆弄之后,我发现这个配置对我有用:

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource") 
  //@ConfigurationProperties("spring.datasource.hikari") can also be used, no difference
    public DataSourceProperties mySQLDataSourceProperties() 
        return new DataSourceProperties();
    

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource.hikari")
    public DataSource mySQLDataSource() 
        return mySQLDataSourceProperties().initializeDataSourceBuilder().build();
    

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public HikariConfig hikariConfig() 
        return new HikariConfig();
    

    @Bean
    public DataSource dataSource() 
        return new HikariDataSource(hikariConfig());
    

我必须在 application.properties 中添加这些设置:

# this is absolutely mandatory otherwise BeanInstantiationException in mySQLDataSource ! 
spring.datasource.url=$JDBC_CONNECTION_STRING

spring.datasource.hikari.jdbc-url=$JDBC_CONNECTION_STRING

spring.datasource.hikari.username=user
spring.datasource.hikari.password=pass

【讨论】:

你调用hikariConfig()mySQLDataSourceProperties()@Bean方法的方式不是直接坏了吗?我不认为 Spring 足够聪明来代理这些调用,假设你得到一个空的 not-configured-by-properties 实例?但是,那些 @Bean 方法可以接受参数,那些是初始化的 bean。参见例如logicbig.com/tutorials/spring-framework/spring-core/… 我也必须在我的属性中添加url

以上是关于如何在 Spring Boot 中将 HikariCP 与两个数据源结合使用 Flyway的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot : ORM 框架 JPA 与连接池 Hikari

无法在 Spring Boot 中为 Hikari 设置 keepAlive Time 配置

使用 Spring Boot 的 Mysql 的 Hikari 配置

带有PostgreSQL,Flyway和Hikari的Spring Boot 2:驱动程序声称不接受jdbcUrl

Spring Boot Hikari 配置

Spring boot + hikari - dataSource or dataSourceClassName or jdbcUrl is required issue