SpringBoot 面试题, 在 Spring Boot 中如何实现多数据源配置?
SpringBoot 面试题, 在 Spring Boot 中如何实现多数据源配置?
QA
Step 1
Q:: 在 Spring Boot 中如何实现多数据源配置?
A:: 在 Spring Boot 中实现多数据源配置的步骤如下:
1.
添加依赖:在 pom.xml
文件中添加 Spring Boot Starter Data JPA 和相关数据库驱动的依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
2.
配置数据源:在 application.yml
文件中配置多个数据源。
spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/primary_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
secondary:
url: jdbc:mysql://localhost:3306/secondary_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
3.
创建配置类:为每个数据源创建配置类,并标注 @Primary
注解指定主要数据源。
@Configuration
public class DataSourceConfig {
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
}
4.
配置事务管理器:为每个数据源配置事务管理器。
@Configuration
@EnableTransactionManagement
public class TransactionManagerConfig {
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
return new DataSourceTransactionManager(primaryDataSource);
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
return new DataSourceTransactionManager(secondaryDataSource);
}
}
5.
配置 JPA 实体管理器:为每个数据源配置 JPA 实体管理器。
@Configuration
@EnableJpaRepositories(
basePackages = "com.example.primary.repository",
entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager"
)
public class PrimaryDataSourceConfig {
@Primary
@Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("primaryDataSource") DataSource primaryDataSource) {
return builder
.dataSource(primaryDataSource)
.packages("com.example.primary.entity")
.persistenceUnit("primaryPU")
.build();
}
}
@Configuration
@EnableJpaRepositories(
basePackages = "com.example.secondary.repository",
entityManagerFactoryRef = "secondaryEntityManagerFactory",
transactionManagerRef = "secondaryTransactionManager"
)
public class SecondaryDataSourceConfig {
@Bean(name = "secondaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
return builder
.dataSource(secondaryDataSource)
.packages("com.example.secondary.entity")
.persistenceUnit("secondaryPU")
.build();
}
}
Step 2
Q:: 如何在 Spring Boot 中动态切换数据源?
A:: 在 Spring Boot 中动态切换数据源可以通过实现 AbstractRoutingDataSource
类来实现。首先,定义一个自定义的 RoutingDataSource
类来确定当前使用的数据源。
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSourceType();
}
}
然后,使用 ThreadLocal
存储当前数据源的信息。
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSourceType(String dataSourceType) {
contextHolder.set(dataSourceType);
}
public static String getDataSourceType() {
return contextHolder.get();
}
public static void clearDataSourceType() {
contextHolder.remove();
}
}
最后,在配置类中定义多个数据源,并使用 DynamicRoutingDataSource
。
@Configuration
public class DataSourceConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public DataSource dataSource() {
DynamicRoutingDataSource routingDataSource = new DynamicRoutingDataSource();
Map<Object, Object> dataSourceMap = new HashMap<>();
dataSourceMap.put("primary", primaryDataSource());
dataSourceMap.put("secondary", secondaryDataSource());
routingDataSource.setTargetDataSources(dataSourceMap);
routingDataSource.setDefaultTargetDataSource(primaryDataSource());
return routingDataSource;
}
}
用途
面试多数据源配置的目的是了解候选人对 Spring Boot 及其数据访问层的理解和掌握程度。在实际生产环境中,多数据源配置常用于以下场景:\n\n`1.` **读写分离**:通过配置多个数据源,可以将读操作和写操作分开,提高系统性能和数据库负载能力。\n`2.` **分库分表**:对于大规模数据,可以通过分库分表的方式来提高系统性能和数据访问效率。\n`3.` **多租户架构**:在 SaaS 应用中,不同租户的数据存储在不同的数据库中,使用多数据源配置可以方便地实现多租户数据隔离。\n`4.` **数据迁移**:在数据迁移过程中,需要同时访问旧数据库和新数据库,以确保数据迁移的正确性和完整性。\n\n相关问题
🦆
Spring Boot 中的 @Primary 注解有什么作用?▷
🦆
Spring Boot 中如何配置 JPA?▷
🦆
Spring Boot 中如何实现事务管理?▷