繁体   English   中英

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

[英]How to use HikariCP in Spring Boot with two datasources in conjunction with Flyway

我想在我的 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 停止创建模式并显示警告。 有没有其他方法可以解决这个问题?

声明您自己的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 特定的配置。

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

    @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

我使用了以下方法

    first.datasource.jdbc-url=jdbc-url
    first.datasource.username=username
    first.datasource.password=password
    .
    .
    .
    .
    =================== In Java Configuration File ==================
    
    @Primary
   @Bean(name = "firstDataSource")
        @ConfigurationProperties(prefix = "first.datasource")
        public DataSource dataSource() {
            return DataSourceBuilder.create().build();
        }
    

@Primary
        @Bean(name = "firstEntityManagerFactory")
        public LocalContainerEntityManagerFactoryBean barEntityManagerFactory(EntityManagerFactoryBuilder builder,
                @Qualifier("firstDataSource") DataSource dataSource) {
            Map<String, String> props = new HashMap<String, String>();
            props.put("spring.jpa.database-platform",  "org.hibernate.dialect.Oracle12cDialect");
    .
    .
    .
    
            return builder.dataSource(dataSource).packages("com.first.entity").persistenceUnit("firstDB")
                    .properties(props)
                    .build();
        }

    @Primary
        @Bean(name = "firstTransactionManager")
        public PlatformTransactionManager firstTransactionManager(
                @Qualifier("firstEntityManagerFactory") EntityManagerFactory firstEntityManagerFactory) {
            return new JpaTransactionManager(firstEntityManagerFactory);
        }

second.datasource.jdbc-url=jdbc-url
second.datasource.username=username
second.datasource.password=password
.
.
.
.
=================== In Java Configuration File ==================

   @Bean(name = "secondDataSource")
    @ConfigurationProperties(prefix = "second.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "secondEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean barEntityManagerFactory(EntityManagerFactoryBuilder builder,
            @Qualifier("secondDataSource") DataSource dataSource) {
        Map<String, String> props = new HashMap<String, String>();
        props.put("spring.jpa.database-platform",  "org.hibernate.dialect.Oracle12cDialect");
.
.
.

        return builder.dataSource(dataSource).packages("com.second.entity").persistenceUnit("secondDB")
                .properties(props)
                .build();
    }

    @Bean(name = "secondTransactionManager")
    public PlatformTransactionManager secondTransactionManager(
            @Qualifier("secondEntityManagerFactory") EntityManagerFactory secondEntityManagerFactory) {
        return new JpaTransactionManager(secondEntityManagerFactory);
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM