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

Tho*_*asW 15 java flyway spring-boot hikaricp

我想在我的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);
 }
Run Code Online (Sandbox Code Playgroud)

我在我的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
Run Code Online (Sandbox Code Playgroud)

不可思议的是,这些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"
Run Code Online (Sandbox Code Playgroud)

创建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());
}
Run Code Online (Sandbox Code Playgroud)

解决了我的问题:

 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"
Run Code Online (Sandbox Code Playgroud)

但是然后Flyway显示了一些之前未显示的奇怪警告,我必须在运行Spring应用程序之前手动创建数据库Schema,即:create schema不再起作用.

[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) 
Run Code Online (Sandbox Code Playgroud)

My 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,
Run Code Online (Sandbox Code Playgroud)

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

And*_*son 11

声明自己DataSource已经禁止Spring Boot自动配置数据源.换句话说,这不会产生任何影响:

@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
Run Code Online (Sandbox Code Playgroud)

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

@Bean
@Primary
@ConfigurationProperties("spring.datasource.hikari")
public DataSource mySQLDataSource() {
    return mySQLDataSourceProperties().initializeDataSourceBuilder().build();
}
Run Code Online (Sandbox Code Playgroud)

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


Tho*_*asW 6

谢谢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());
    }
Run Code Online (Sandbox Code Playgroud)

并且我必须在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
Run Code Online (Sandbox Code Playgroud)