簡體   English   中英

多個數據源彈出啟動

[英]Multiple datasources spring boot

我已經嘗試了幾個小時才能使這個工作,看看文檔:

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html

...各種stackoverflow問題和我能找到的其他東西。 但是,這證明是難以捉摸的(閱讀,讓我想把頭撞在牆上)。 任何幫助都是如此,所以歡迎!

我需要連接到兩個不同的數據庫(聽起來很簡單?)我有一個Spring Boot Web應用程序使用spring-boot-starter-data-jpa依賴項,它可以很好地利用單個數據源 現在我需要與第二個數據庫交談,但事情並沒有奏效。 我以為我已經工作了一段時間,但事實證明一切都要進入主數據庫。

我目前正試圖讓這個工作在一個單獨的“減少”項目,試圖減少運動部件的數量,但仍然沒有工作。

我有兩個@Configuration類 - 每個數據源一個,這是第一個:

@Configuration
@EnableJpaRepositories(
        entityManagerFactoryRef = "firstEntityManagerFactory",
        transactionManagerRef = "firstTransactionManager",
        basePackages = {"mystuff.jpaexp.jpatest"})
public class DataConfiguration {
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "app.datasource1")
    public DataSourceProperties firstDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("app.datasource1")
    public DataSource firstDataSource() {
        return firstDataSourceProperties().initializeDataSourceBuilder().
                driverClassName("org.postgresql.Driver").
                url("jdbc:postgresql://localhost:5432/experiment1").
                username("postgres").
                password("postgres").
                build();
    }

    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean firstEntityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setPackagesToScan("mystuff.jpaexp.jpatest");
        factory.setDataSource(firstDataSource());
        factory.setPersistenceUnitName("ds1");
        return factory;
    }

    @Primary
    @Bean
    public PlatformTransactionManager firstTransactionManager() {
        return new JpaTransactionManager();
    }
}

這是第二個:

@Configuration
@EnableJpaRepositories(
        entityManagerFactoryRef = "secondEntityManagerFactory",
        transactionManagerRef = "secondTransactionManager",
        basePackages = {"mystuff.jpaexp.jpatest2"})
public class Otherconfiguration {
    @Bean
    @ConfigurationProperties(prefix = "app.datasource2")
    public DataSourceProperties secondDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("app.datasource2")
    public DataSource secondDataSource() {
        return secondDataSourceProperties().initializeDataSourceBuilder().
                driverClassName("org.postgresql.Driver").
                url("jdbc:postgresql://localhost:5432/experiment2").
                username("postgres").
                password("postgres").
                build();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean secondEntityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setJpaVendorAdapter(vendorAdapter);
        factory.setPackagesToScan("mystuff.jpaexp.jpatest2");
        factory.setDataSource(secondDataSource());
        factory.setPersistenceUnitName("ds2");
        return factory;
    }

    @Bean
    public PlatformTransactionManager secondTransactionManager() {
        return new JpaTransactionManager();
    }
}

在兩個包mystuff.jpaexp.jpatestmystuff.jpaexp.jpatest2每一個中,我都有一個簡單的@EntityCrudRepository ,它們應該分別與第一個和第二個數據源一起使用。

然后我有一個main()來測試:

@SpringBootApplication
@EnableAutoConfiguration(exclude = {WebMvcAutoConfiguration.class})
@ComponentScan("mystuff.jpaexp.*")
public class SpringbootCommandLineApp implements CommandLineRunner {
    private final MyRepository myRepository;
    private final OtherRepo otherRepo;

    @Autowired
    public SpringbootCommandLineApp(MyRepository myRepository, OtherRepo otherRepo) {
        this.myRepository = myRepository;
        this.otherRepo = otherRepo;
    }

    public static void main(String[] args) {
        new SpringApplicationBuilder(SpringbootCommandLineApp.class)
                .web(false)
                .run(args);
    }

    @Override
    public void run(String... args) throws Exception {
        myRepository.save(new MyEntity("Goodbye or hello"));
        myRepository.save(new MyEntity("What?"));
        myRepository.save(new MyEntity("1,2,3..."));

        myRepository.findAll().forEach(System.out::println);

        otherRepo.save(new MyEntity2("J Bloggs"));
        otherRepo.save(new MyEntity2("A Beecher"));
        otherRepo.save(new MyEntity2("C Jee"));

        otherRepo.findAll().forEach(x -> {
            System.out.println("Name:" + x.getName() + ", ID: " + x.getId());
        });
    }
}

最后, application.properties一些道具:

app.datasource1.driver-class-name=org.postgresql.Driver
app.datasource1.url=jdbc:postgresql://localhost:5432/experiment1
app.datasource1.username=postgres
app.datasource1.password=postgres

app.datasource2.driver-class-name=org.postgresql.Driver
app.datasource2.url=jdbc:postgresql://localhost:5432/experiment2
app.datasource2.username=postgres
app.datasource2.password=postgres

這些完全沒有效果 - 事情似乎仍然由spring.datasource.*配置spring.datasource.*相反,這顯然沒用。

最終輸出:

2018-05-25 17:04:00.797  WARN 29755 --- [           main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Tomcat.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.tomcat.jdbc.pool.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
2018-05-25 17:04:00.800  INFO 29755 --- [           main] utoConfigurationReportLoggingInitializer : 

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2018-05-25 17:04:00.803 ERROR 29755 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Cannot determine embedded database driver class for database type NONE

Action:

If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).


Process finished with exit code 1

我知道這里有很多代碼,對不起,謝謝!

嗯,花了很長時間,我認為有一些微妙的問題,還有一些可以簡化的部分:

  • 只需要一個DataSourceProperties - 兩個數據源都可以使用它
  • DataSource bean定義需要@ConfigurationProperties ,而不是DataSourceProperties bean
  • 認為 @ComponentScan("mystuff.jpaexp.*")注釋是不正確的,用@ComponentScan替換它似乎修復了一些bean定義
  • 我必須在JpaTransactionManager定義中注入一個EntityManagerFactorreturn new JpaTransactionManager(secondEntityManagerFactory().getObject());
  • 我添加了一個JpaProperties bean,並明確地將這些屬性拉入VendorAdapter

VendorAdapter / JpaProperties的變化看起來像這樣(JpaProperties與供應商無關,但它上面有一個hibernateProperties似乎很奇怪?!):

@Bean
public LocalContainerEntityManagerFactoryBean secondEntityManagerFactory() {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(true);

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("...entity-package...");
    factory.setDataSource(secondDataSource());
    Map<String, String> props = new HashMap<>();
    props.putAll(secondJpaProperties().getProperties());
    props.putAll(secondJpaProperties().getHibernateProperties(secondDataSource()));
    factory.setJpaPropertyMap(props);
    factory.setPersistenceUnitName("ds2");
    return factory;
}

@Bean
@ConfigurationProperties(prefix = "jpa.datsource2")
public JpaProperties secondJpaProperties() {
    return new JpaProperties();
}

我認為這足以讓事情順利進行。 此外,為了使嵌入式H2實例恢復生機,各種屬性的永遠如此聰明的默認不再有效,所以我還必須明確所有數據庫屬性:

jpa.datasource1.hibernate.ddl-auto=create
app.datasource1.driver-class-name=org.h2.Driver
app.datasource1.url=jdbc:h2:mem:primary
app.datasource1.username=
app.datasource1.password=

jpa.datasource2.hibernate.ddl-auto=create
app.datasource2.driver-class-name=org.h2.Driver
app.datasource2.url=jdbc:h2:mem:view
app.datasource2.username=
app.datasource2.password=

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM