Spring Boot多資料來源配置
阿新 • • 發佈:2019-02-04
動機
- 在最近的專案中,由於新專案要和老專案整合(新舊業務過渡),因此需要將的資料庫表與老資料庫表做資料庫同步。
方案
- 利用Spring Boot支援多資料來源的特性,配置兩個資料來源來實現該需求。(這篇部落格不討論業務層面的實現方式,只討論多資料來源的配置。)
實現
新建兩個配置類(即加@Configuration註解的類),一個為PrimaryDatasourceConfig,用來配置本專案的資料來源;另一個叫SecondDatasourceCOnfig,用來配置需要同步的資料來源。程式碼如下:
@Configuration public class PrimaryDatasourceConfig
其中@Primary註解是用來指定優先使用的資料來源。
@ConfigurationProperties是用來指定該資料遠,從application.properties中讀取字首為“XXX”的配置作為該資料來源的配置。
並且由於這兩個資料來源的型別都是DataSource,因此我們需要為這兩個Bean指定不同的名稱,這樣能夠在後面注入的時候通過名稱來注入相應的Bean。再新建兩個配置類,來配置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<String, String> 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<String, String> 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); } }
- 當使用第二個資料來源的時候,@Autowired時用@Qualifier指定第二個資料來源即可。例如要注入jdbcTemplate。
@Autowired
@Qualifier("secondJdbcTemplate")
private JdbcTemplate jdbcTemplate;
如果沒有@Qualifier("secondJdbcTemplate")
,預設指定Primary資料來源。