【问题标题】:How to use a second data source in spring?spring 如何使用第二个数据源?
【发布时间】:2019-10-23 20:37:08
【问题描述】:

我在这里下载了示例代码

https://github.com/spring-projects/spring-data-examples/tree/master/jpa/multiple-datasources

但我仍然不明白存储库是如何连接到数据源的。即使我查看配置类,它也没有引用存储库。在存储库接口内部,它不引用数据源或配置。

那么当您使用两个不同的存储库进行保存时,它如何知道每个存储库要转到哪个数据源?

【问题讨论】:

  • 我认为是因为每个配置类中定义的包组件扫描

标签: spring-boot datasource spring-repositories


【解决方案1】:

在带有您链接的示例的存储库中,每个配置类都用​​@EnableJpaRepositories 注释,它仅在带注释的类和子包的包中扫描存储库 - 这是数据源和存储库之间发生关系的地方。

【讨论】:

  • 那么repos是基于同一个包中的一个Config类来配置的吗?这么奇怪的设计,为什么呢?如果我的 repos 分布在许多不同的包中怎么办?我必须为每个人创建一个配置,即使我希望他们都使用同一个?如果我不创建配置,它会以某种方式使用默认值吗?
【解决方案2】:

注意配置(注释为/*重要*/)

OrderConfig

@Configuration

/* important */
@EnableJpaRepositories(entityManagerFactoryRef = "orderEntityManagerFactory",
        transactionManagerRef = "orderTransactionManager")

class OrderConfig {

    @Bean
    PlatformTransactionManager orderTransactionManager() {
        return new JpaTransactionManager(orderEntityManagerFactory().getObject());
    }

    @Bean
    LocalContainerEntityManagerFactoryBean orderEntityManagerFactory() {

        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        /* important */
        factoryBean.setDataSource(orderDataSource());
        factoryBean.setJpaVendorAdapter(vendorAdapter);
        factoryBean.setPackagesToScan(OrderConfig.class.getPackage().getName());

        return factoryBean;
    }

    @Bean
    DataSource orderDataSource() {

        return new EmbeddedDatabaseBuilder().//
                setType(EmbeddedDatabaseType.HSQL).//
                setName("orders").//
                build();
    }
}

还有CustomerConfig

@Configuration

/* important */
@EnableJpaRepositories(entityManagerFactoryRef = "customerEntityManagerFactory",
        transactionManagerRef = "customerTransactionManager")

class CustomerConfig {

    @Bean
    PlatformTransactionManager customerTransactionManager() {
        return new JpaTransactionManager(customerEntityManagerFactory().getObject());
    }

    @Bean
    LocalContainerEntityManagerFactoryBean customerEntityManagerFactory() {

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        /* important */
        factoryBean.setDataSource(customerDataSource());
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setPackagesToScan(CustomerConfig.class.getPackage().getName());

        return factoryBean;
    }

    @Bean
    DataSource customerDataSource() {

        return new EmbeddedDatabaseBuilder().//
                setType(EmbeddedDatabaseType.HSQL).//
                setName("customers").//
                build();
    }
}

最后是DataInitializer中的@Transactional注解

/* important */
@Transactional("customerTransactionManager")

public CustomerId initializeCustomer() {
    return customers.save(new Customer("Dave", "Matthews")).getId();
}

使用在CustomerConfig中配置的customerTransactionManager

和,

/* important */
@Transactional("orderTransactionManager")

public Order initializeOrder(CustomerId customer) {

   Assert.notNull(customer, "Customer identifier must not be null!");

   Order order = new Order(customer);
   order.add(new LineItem("Lakewood Guitar"));

   return orders.save(order);
}

使用在OrderConfig中配置的orderTransactionManager

基本上,您正在配置不同的datasources、不同的entityManagers、不同的transactionManagers,并根据您的选择专门引用它们。

【讨论】:

  • 那么repos是基于同一个包中的一个Config类来配置的吗?这么奇怪的设计,为什么呢?如果我的 repos 分布在许多不同的包中怎么办?我必须为每个人创建一个配置,即使我希望他们都使用同一个?如果我不创建配置,它会以某种方式使用默认值吗?
猜你喜欢
  • 2018-02-26
  • 2019-04-24
  • 1970-01-01
  • 1970-01-01
  • 2015-11-06
  • 2017-06-24
  • 2018-04-10
  • 2019-07-21
  • 2019-12-16
相关资源
最近更新 更多