Spring Boot多数据源配置

  • 动机

    • 在最近的项目中,由于新项目要和老项目整合(新旧业务过渡),因此需要将的数据库表与老数据库表做数据库同步。
  • 方案

    • 利用Spring Boot支持多数据源的特性,配置两个数据源来实现该需求。(这篇博客不讨论业务层面的实现方式,只讨论多数据源的配置。)
  • 实现

    1. 新建两个配置类(即加@Configuration注解的类),一个为PrimaryDatasourceConfig,用来配置本项目的数据源;另一个叫SecondDatasourceCOnfig,用来配置需要同步的数据源。代码如下:

      @Configuration
      public class PrimaryDatasourceConfig {
      
          @Bean(name = "primaryDataSource")
          @Primary
          @ConfigurationProperties(prefix = "primary.datasource")
          public DataSource dataSource() {
              return DataSourceBuilder.create().build();
          }
      }
      
      @Configuration
      public class SecondDatasourceConfig {
      
          @Bean(name = "secondDataSource")
          @ConfigurationProperties(prefix = "second.datasource")
          public DataSource dataSource() {
              return DataSourceBuilder.create().build();
          }
      }

      其中@Primary注解是用来指定优先使用的数据源。
      @ConfigurationProperties是用来指定该数据远,从application.properties中读取前缀为“XXX”的配置作为该数据源的配置。
      并且由于这两个数据源的类型都是DataSource,因此我们需要为这两个Bean指定不同的名称,这样能够在后面注入的时候通过名称来注入相应的Bean。

    2. 再新建两个配置类,来配置EntityManager与JdbcTemplate。代码如下:

      @Configuration
      @EnableTransactionManagement(proxyTargetClass = true)//开启注解管理方式
      @EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryPrimary",//指定LocalContainerEntityManagerFactoryBean
              transactionManagerRef = "transactionManagerPrimary",//指定使用哪个EntityManager
              basePackages = { "org.model" })//指定该数据源对于的model包
      public class RepositoryPrimaryConfig {
      
          @Autowired
          private JpaProperties jpaProperties;
      
          @Autowired
          @Qualifier("primaryDataSource")//指定使用哪个数据源
          private DataSource primaryDataSource;
      
          @Bean(name = "entityManagerPrimary")
          @Primary//由于这个数据源是Primary,因此这里配置的Bean都加上@Primary注解。
          //即在@Autowired时,没有用指定@Qualifier指定哪个数据源配置时,默认使用这个。
          public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
              return entityManagerFactory(builder).getObject()
                      .createEntityManager();
          }
      
          @Bean(name = "entityManagerFactoryPrimary")
          @Primary
          public LocalContainerEntityManagerFactoryBean entityManagerFactory(
                  EntityManagerFactoryBuilder builder) {
              return builder.dataSource(primaryDataSource)
                      .properties(getVendorProperties(primaryDataSource))
                      .packages("org.model") // 设置实体类所在位置
                      .persistenceUnit("PrimaryPersistenceUnit")
                      .build();
          }  
      
          private Map getVendorProperties(DataSource dataSource) {
              return jpaProperties.getHibernateProperties(dataSource);
          }
      
          @Bean(name = "transactionManagerPrimary")
          @Primary
          PlatformTransactionManager transactionManager(
                  EntityManagerFactoryBuilder builder) {
              return new JpaTransactionManager(
                      entityManagerFactory(builder).getObject());
          }
      
          @Bean
          @Primary
          public JdbcTemplate primaryJdbcTemplate(DataSource dataSource) {
              return new JdbcTemplate(dataSource);
          }
      }
      
      @Configuration
      @EnableTransactionManagement(proxyTargetClass = true)
      @EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactorySecond",
              transactionManagerRef = "transactionManagerSecond",
              basePackages = { "org.second" })
      public class RepositorySecondConfig {
      
          @Autowired
          private JpaProperties jpaProperties;
      
          @Autowired
          @Qualifier("secondDataSource")
          private DataSource secondDataSource;
      
          @Bean(name = "entityManagerSecond")
          public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
              return entityManagerFactory(builder).getObject()
                      .createEntityManager();
          }
      
          @Bean(name = "entityManagerFactorySecond")
          public LocalContainerEntityManagerFactoryBean entityManagerFactory(
                  EntityManagerFactoryBuilder builder) {
              return builder.dataSource(secondDataSource)
                      .properties(getVendorProperties(jwcDataSource))
                      .packages("org.second") // 设置实体类所在位置
                      .persistenceUnit("SecondPersistenceUnit").build();
          }
      
          private Map getVendorProperties(DataSource dataSource) {
              return jpaProperties.getHibernateProperties(dataSource);
          }
      
          @Bean(name = "transactionManagerSecond")
          PlatformTransactionManager transactionManager(
                  EntityManagerFactoryBuilder builder) {
              return new JpaTransactionManager(
                      entityManagerFactory(builder).getObject());
          }
      
          @Bean(name = "secondJdbcTemplate")
          public JdbcTemplate jdbcTemplate(
                  @Qualifier("secondDataSource") DataSource dataSource) {
              return new JdbcTemplate(dataSource);
          }
      }
    3. 当使用第二个数据源的时候,@Autowired时用@Qualifier指定第二个数据源即可。例如要注入jdbcTemplate。

      @Autowired
      @Qualifier("secondJdbcTemplate")
      private JdbcTemplate jdbcTemplate;

      如果没有@Qualifier("secondJdbcTemplate"),默认指定Primary数据源。

你可能感兴趣的:(spring-boot,jpa)