我尝试了几个小时才能使它正常工作,请查看文档:

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

...各种stackoverflow问题以及我能找到的其他很多东西。但是,事实证明这是难以捉摸的(阅读,让我想把头撞在墙上)。任何帮助都会如此,非常欢迎!

我需要连接到两个不同的数据库(听起来足够简单吗?),并且我有一个使用spring-boot-starter-data-jpa依赖项的Spring Boot Web应用程序,它可以通过单个数据源很好地解决问题。现在,我需要谈谈第二个数据库,但一切都没有进行。我以为我可以使用它一段时间,但事实证明一切都在主数据库中。

我目前正在尝试在一个单独的“缩减”项目中进行此操作,以尝试减少运动部件的数量,但仍无法正常工作。

我有两个@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.*配置的,显然没有用。

最终输出:
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-两个数据源都可以使用它
  • 数据源bean定义上需要
  • @ConfigurationProperties,而不是DataSourceProperties bean
  • 我认为@ComponentScan("mystuff.jpaexp.*")注释不正确,用简单的@ComponentScan替换它似乎可以解决一些Bean定义
  • 的问题。
  • 我必须将EntityManagerFactor注入JpaTransactionManager定义中:return 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=
    

    10-05 21:13
    查看更多