这里我们假设大家已经熟悉 SpringBoot + JPA 连接单个数据库的开发。如果不熟悉,可以参考:Spring Boot 使用数据库
- Pom 依赖和但数据库没有区别,照常引入。
- JAP 的 Entity Object 和 Repository 写法没有任何区别,照常编写。
- 写数据库配置时,过去我们只需定义一个 spring.datasource.* 即可。而现在需要连接多个数据库,我们的配置方式略有变化,配置文件 application.yml 如下:
app:
datasource:
first:
jdbc-url: jdbc:db2://xxx.xxx.xxx.xxx:50000/xxx
username: xxx
password: xxx
maximum-pool-size: 30
continueOnError: true
second:
jdbc-url: jdbc:db2://xxx.xxx.xxx.xxx:50000/xxx
username: xxx
password: xxx
maximum-pool-size: 30
continueOnError: true
这里的 first 和 second 是自定义名,稍后在写数据库的配置类时会用到。
- 写数据库配置类
- 第一个数据库配置(FirstDataSourceConfig.java)
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"com.taikang.cms.warningservice.domain.first"},
entityManagerFactoryRef = "FirstEntityManagerFactory",
transactionManagerRef = "FirstTransactionManager")
public class FirstDataSourceConfig {
@Primary
@Bean(name="FirstDataSource")
@ConfigurationProperties("app.datasource.first")
public HikariDataSource dataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Primary
@Bean(name ="FirstEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
@Qualifier("FirstDataSource") DataSource dataSource){
return builder
.dataSource(dataSource)
.packages("com.taikang.cms.warningservice.domain.first")
.persistenceUnit("first")
.build();
}
@Primary
@Bean(name ="FirstTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("FirstEntityManagerFactory") EntityManagerFactory customerEntityManagerFactory
) {
return new JpaTransactionManager(customerEntityManagerFactory);
}
}
- 第二个数据库配置(SecondDataSourceConfig.java)
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = {"com.taikang.cms.warningservice.domain.second"},
entityManagerFactoryRef = "SecondEntityManagerFactory",
transactionManagerRef = "SecondTransactionManager")
public class SecondDataSourceConfig {
@Bean(name="SecondDataSource")
@ConfigurationProperties("app.datasource.second")
public HikariDataSource dataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean(name ="SecondEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
@Qualifier("SecondDataSource") DataSource dataSource){
return builder
.dataSource(dataSource)
.packages("com.taikang.cms.warningservice.domain.second")
.persistenceUnit("second")
.build();
}
@Bean(name ="SecondTransactionManager")
public PlatformTransactionManager transactionManager(
@Qualifier("FirstEntityManagerFactory") EntityManagerFactory customerEntityManagerFactory
) {
return new JpaTransactionManager(customerEntityManagerFactory);
}
}
- 特别注意一下 @EnableJpaRepositories(...) 这个注解,他用来定义 JPA Repositories 所对应的具体数据库源。
- 可以了! 启动服务试试看了!
过程碰到的坑
变量名和数据库字段的映射规则(JPA naming strategy)失效了?
通常我们的 sql 命名多个单词都是下划线隔开,而 java 的变量名则是采用驼峰。熟悉 JPA 的伙伴知道,spring 在这里会帮我们自动把下划线命名和驼峰命名进行映射。但不知为何,当我采用多个数据源后,这个自动映射就失效了,会报错,诸如找不到字段,找不到对应库表等问题。
解决方法,我们只需要稍微修改一下我们数据源配置类的 entityManagerFactory 方法,改写代码如下:
@Bean(name ="XXX")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,
@Qualifier("XXX") DataSource dataSource){
return builder
.dataSource(dataSource)
.packages("com.demo.xxx.xxx")
.persistenceUnit("xxx")
.properties(jpaProperties())
.build();
}
protected Map<String, Object> jpaProperties() {
Map<String, Object> props = new HashMap<>();
props.put("hibernate.physical_naming_strategy", SpringPhysicalNamingStrategy.class.getName());
props.put("hibernate.implicit_naming_strategy", SpringImplicitNamingStrategy.class.getName());
return props;
}
网友评论