多个数据源回退

时间:2018-07-06 08:20:54

标签: java spring-boot datasource

建议后更新:

我有一个Springboot Java应用程序和两个在application.properties中定义的数据源:

spring.jpa.hibernate.ddl-auto=update

#online
spring.datasource.url=jdbc:mysql://172.17.0.2:3306/gcdb?allowPublicKeyRetrieval=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driverClassName=com.mysql.jdbc.Driver 

#offline
spring.secondDatasource.url=jdbc:h2:mem:gcdboff
spring.secondDatasource.username=root
spring.secondDatasource.password=root
spring.secondDatasource.driverClassName=org.h2.Driver

# Enabling H2 Console
spring.h2.console.enabled=true
spring.h2.console.path=/h2

将凭据从“数据源”手动更改为“ secondDatasource”后,两个连接都可以正常工作。

但是现在我想添加一个备用。如果“数据源”不可用,请使用“ secondDatasource”。

我发现了以下溶液。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

@SpringBootApplication
public class GCApplication {

    public static void main(String[] args) {
        SpringApplication.run(GCApplication.class, args);
    }
/**/
    @Bean
    @Primary
    @ConfigurationProperties(prefix="spring.datasource")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix="spring.secondDatasource")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }
/**/
}

但是现在没有人可以参加。该应用程序以以下错误结尾,我不知道如何纠正该错误。

2018-07-06 09:52:30.805 ERROR 28073 --- [           main]     o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unsatisfied dependency expressed through method 'entityManagerFactory' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityManagerFactoryBuilder' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unsatisfied dependency expressed through method 'entityManagerFactoryBuilder' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaVendorAdapter' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.jpa.JpaVendorAdapter]: Factory method 'jpaVendorAdapter' threw exception; nested exception is java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:732) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
[...]

谢谢您的帮助!

3 个答案:

答案 0 :(得分:0)

该异常很简单,并说:

  

java.lang.IllegalArgumentException:需要dataSource或dataSourceClassName或jdbcUrl

因此,这意味着您缺少一个数据源的配置属性。

如果我们查看您的属性文件,可以看到spring.datasource.driverClassName配置属性。

因此,您缺少driverClassName数据库的MySQL,需要指定它。

答案 1 :(得分:0)

我找到了解决我问题的方法。我希望它能对您有所帮助。使用以下代码,在第一个数据连接失败后,选择第二个数据连接:

在GCApplication中:

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

@SpringBootApplication
public class GCApplication 
{
    public static void main(String[] args) 
    {
        SpringApplication.run(GCApplication.class, args);
    }

    @Primary
    @Bean
    public DataSource getDataSource(
        @Qualifier("first") DataSourceProperties first,
        @Qualifier("second") DataSourceProperties second)
    {
        int i = 0;
        final DataSource firstDataSource = first.initializeDataSourceBuilder().build();
        final DataSource secondDataSource = second.initializeDataSourceBuilder().build();
        try
        {
            firstDataSource.getConnection();
            return firstDataSource;
        } 
        catch (Exception e) 
        {
            return secondDataSource;
        }
    }

    @Primary
    @Bean("first")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSourceProperties primaryDataSource()     
    {
        final DataSourceProperties dataSourceProperties = new DataSourceProperties();
        dataSourceProperties.setUrl("jdbc:mysql://172.17.0.2:3306/gcdb?allowPublicKeyRetrieval=true&useSSL=false");
        dataSourceProperties.setDriverClassName("com.mysql.jdbc.Driver");
        dataSourceProperties.setUsername("root");
        dataSourceProperties.setPassword("root");
        return dataSourceProperties;
    }

    @Bean("second")
    public DataSourceProperties secondaryDataSource() {
        final DataSourceProperties dataSourceProperties = new DataSourceProperties();
        dataSourceProperties.setUrl("jdbc:h2:mem:gcdboff");
        dataSourceProperties.setDriverClassName("org.h2.Driver");
        dataSourceProperties.setUsername("root");
        dataSourceProperties.setPassword("root");
        return dataSourceProperties;
    }
}

在application.properties中:

spring.jpa.hibernate.ddl-auto=update
spring.jpa.database=default

# Enabling H2 Console
spring.h2.console.enabled=true
spring.h2.console.path=/h2

答案 2 :(得分:0)

只需添加到@Tagamoga的答案中,就可以将三个bean:getDataSource,primaryDataSource和secondaryDataSource添加到一个单独的类中,并使用@Configuration对其进行注释。在这种情况下,您将具有单独的配置,并且仍然可以使用属性文件来配置数据库连接。 像这样:

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.jdbc.DataSourceInitializationMode;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

@Configuration
public class DatabaseConfig {

    @Value("${datasource.primary.url}")
    String primaryDSUrl;

    @Value("${datasource.primary.platform}")
    String primaryDSPlatform;

    @Value("${datasource.primary.username}")
    String primaryDSUsername;

    @Value("${datasource.primary.password}")
    String primaryDSPassword;

    @Value("${datasource.secondary.url}")
    String secondaryDSUrl;

    @Value("${datasource.secondary.platform}")
    String secondaryDSPlatform;

    @Value("${datasource.secondary.username}")
    String secondaryDSUsername;

    @Value("${datasource.secondary.password}")
    String secondaryDSPassword;

    @Primary
    @Bean
    public DataSource getDataSource(
            @Qualifier("first") DataSourceProperties first,
            @Qualifier("second") DataSourceProperties second) {
        final DataSource firstDataSource = first.initializeDataSourceBuilder().build();
        final DataSource secondDataSource = second.initializeDataSourceBuilder().build();
        try {
            firstDataSource.getConnection();
            return firstDataSource;
        } catch (Exception e) {
            return secondDataSource;
        }
    }

    @Primary
    @Bean("first")
    public DataSourceProperties primaryDataSource() {
        final DataSourceProperties dataSourceProperties = new DataSourceProperties();
        dataSourceProperties.setUrl(primaryDSUrl);
        dataSourceProperties.setPlatform(primaryDSPlatform);
        dataSourceProperties.setUsername(primaryDSUsername);
        dataSourceProperties.setPassword(primaryDSPassword);
        dataSourceProperties.setInitializationMode(DataSourceInitializationMode.ALWAYS);
        return dataSourceProperties;
    }

    @Bean("second")
    public DataSourceProperties secondaryDataSource() {
        final DataSourceProperties dataSourceProperties = new DataSourceProperties();
        dataSourceProperties.setUrl(secondaryDSUrl);
        dataSourceProperties.setPlatform(secondaryDSPlatform);
        dataSourceProperties.setUsername(secondaryDSUsername);
        dataSourceProperties.setPassword(secondaryDSPassword);
        dataSourceProperties.setInitializationMode(DataSourceInitializationMode.ALWAYS);
        return dataSourceProperties;
    }
}

以及属性文件:

#Datasource Primary
datasource.primary.platform=oracle
datasource.primary.url=jdbc:oracle:thin:@localhost:1521:orcl
datasource.primary.username=LCO2TL
datasource.primary.password=LCO2TL2020

#Datasource Secondary
datasource.secondary.platform=h2
datasource.secondary.url=jdbc:h2:mem:test"
datasource.secondary.username=root
datasource.secondary.password=root