引言
在现代企业级应用开发中,往往需要同时访问多个数据库来满足不同的业务需求。Spring Boot 作为一个快速开发的框架,提供了非常便捷的方式来配置和管理多数据源。本文将详细介绍如何在 Spring Boot 项目中配置多数据源,并通过实际代码示例展示其应用场景。
一、为什么要配置多数据源?
在实际项目中,配置多数据源的场景非常常见,例如:
- 读写分离:为了提高数据库的读写性能,通常会将读操作和写操作分别分配到不同的数据库实例上。
- 分库分表:当单个数据库无法满足性能需求时,可以将数据分散到多个数据库中。
- 跨部门数据库访问:不同部门或业务线使用独立的数据库,应用需要同时访问多个数据库。
二、Spring Boot 配置多数据源的基本步骤
1. 引入依赖
首先,我们需要在 pom.xml
中引入必要的依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
2. 配置多数据源
在 application.yml
中配置多个数据源:
spring:
datasource:
primary:
jdbc-url: jdbc:mysql://localhost:3306/primary_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
secondary:
jdbc-url: jdbc:mysql://localhost:3306/secondary_db
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
3. 创建数据源配置类
接下来,我们需要创建两个配置类,分别用于管理主数据源和次数据源:
@Configuration
public class PrimaryDataSourceConfig {
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("primaryDataSource") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages("com.example.primary.domain")
.persistenceUnit("primary")
.build();
}
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager(
@Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
@Configuration
public class SecondaryDataSourceConfig {
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("secondaryDataSource") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages("com.example.secondary.domain")
.persistenceUnit("secondary")
.build();
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(
@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
4. 使用多数据源
在业务代码中,可以通过 @Qualifier
注解指定使用哪个数据源:
@Service
public class UserService {
@Autowired
@Qualifier("primaryEntityManagerFactory")
private EntityManagerFactory primaryEntityManagerFactory;
@Autowired
@Qualifier("secondaryEntityManagerFactory")
private EntityManagerFactory secondaryEntityManagerFactory;
public void saveUser(User user) {
EntityManager em = primaryEntityManagerFactory.createEntityManager();
em.getTransaction().begin();
em.persist(user);
em.getTransaction().commit();
em.close();
}
public void saveOrder(Order order) {
EntityManager em = secondaryEntityManagerFactory.createEntityManager();
em.getTransaction().begin();
em.persist(order);
em.getTransaction().commit();
em.close();
}
}
三、高级配置:事务管理与动态数据源选择
1. 事务管理
在多数据源场景下,事务管理变得更加复杂。Spring Boot 提供了 TransactionManager
来管理事务。可以通过 @Transactional
注解来指定哪个数据源的事务:
@Transactional("primaryTransactionManager")
public void saveUser(User user) {
// 业务逻辑
}
@Transactional("secondaryTransactionManager")
public void saveOrder(Order order) {
// 业务逻辑
}
2. 动态数据源选择
在某些场景下,我们需要根据业务逻辑动态选择数据源。可以通过自定义 AbstractRoutingDataSource
来实现:
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSource();
}
}
然后在配置类中定义动态数据源:
@Bean
public DataSource dynamicDataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("primary", primaryDataSource());
targetDataSources.put("secondary", secondaryDataSource());
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(primaryDataSource());
return dynamicDataSource;
}
最后,在业务代码中通过线程上下文切换数据源:
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
四、总结
通过本文的详细介绍,我们了解了在 Spring Boot 项目中配置多数据源的基本步骤和进阶技巧。多数据源配置不仅能够满足复杂的业务需求,还能提高系统的扩展性和性能。希望本文能为你提供实用的参考和指导,帮助你在实际项目中更好地应用多数据源配置。
五、参考资料
- [Spring Boot官方文档](https://docs.spring.io/spring-