## Spring Boot 配置多数据源
简介
在实际开发中,我们常常需要连接多个数据库,例如读写分离、连接不同类型的数据库等。Spring Boot 提供了便捷的方式来配置多数据源,本文将详细介绍如何在 Spring Boot 应用中配置多个数据源。### 1. 添加依赖首先,确保你的项目中包含了 Spring Boot Starter Data JPA 和所需数据库的驱动依赖。例如,如果你要连接 MySQL 和 PostgreSQL 数据库,需要添加以下依赖:```xml
org.springframework.bootspring-boot-starter-data-jpa
mysqlmysql-connector-javaruntime
org.postgresqlpostgresqlruntime
```### 2. 配置多数据源Spring Boot 提供了多种方式配置多数据源,这里介绍两种常用的方式:#### 2.1 基于`@ConfigurationProperties`的配置方式这种方式比较简洁直观,适合简单的多数据源配置。1. 创建数据源配置类:```java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;@Configuration
public class DataSourceConfig {@Bean(name = "primaryDataSource")@Primary // 设置为主数据源@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();}
}
```2. 在 `application.properties` 或 `application.yml` 文件中配置数据库连接信息:```properties
spring.datasource.primary.url=jdbc:mysql://localhost:3306/primary_db
spring.datasource.primary.username=root
spring.datasource.primary.password=password
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.secondary.url=jdbc:postgresql://localhost:5432/secondary_db
spring.datasource.secondary.username=postgres
spring.datasource.secondary.password=password
spring.datasource.secondary.driver-class-name=org.postgresql.Driver
```#### 2.2 基于`DataSourceBuilder`的配置方式 (更灵活)这种方式更加灵活,可以自定义更多的数据源配置,例如连接池等。```java
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;@Configuration
public class DataSourceConfig {@Bean(name = "primaryDataSource")@Primarypublic DataSource primaryDataSource() {DataSourceBuilder> dataSourceBuilder = DataSourceBuilder.create();dataSourceBuilder.driverClassName("com.mysql.cj.jdbc.Driver");dataSourceBuilder.url("jdbc:mysql://localhost:3306/primary_db");dataSourceBuilder.username("root");dataSourceBuilder.password("password");return dataSourceBuilder.build();}@Bean(name = "secondaryDataSource")public DataSource secondaryDataSource() {DataSourceBuilder> dataSourceBuilder = DataSourceBuilder.create();dataSourceBuilder.driverClassName("org.postgresql.Driver");dataSourceBuilder.url("jdbc:postgresql://localhost:5432/secondary_db");dataSourceBuilder.username("postgres");dataSourceBuilder.password("password");return dataSourceBuilder.build();}
}
```### 3. 配置`EntityManagerFactory` 和 `JpaTransactionManager`为每个数据源配置对应的 `EntityManagerFactory` 和 `JpaTransactionManager`:```java
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "primaryEntityManagerFactory",transactionManagerRef = "primaryTransactionManager",basePackages = {"com.example.primary"} // 设置 primary 数据源对应的 Repository 包路径
)
public class PrimaryJpaConfig {@Bean(name = "primaryEntityManagerFactory")public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(@Qualifier("primaryDataSource") DataSource dataSource) {return buildEntityManagerFactory(dataSource, "com.example.primary"); // 使用 primary 数据源对应的实体类包路径}@Bean(name = "primaryTransactionManager")public PlatformTransactionManager primaryTransactionManager(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {return new JpaTransactionManager(entityManagerFactory);}// ... 同样的方式配置 secondary 数据源private LocalContainerEntityManagerFactoryBean buildEntityManagerFactory(DataSource dataSource, String packageName) {HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();vendorAdapter.setGenerateDdl(true);LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();factory.setJpaVendorAdapter(vendorAdapter);factory.setPackagesToScan(packageName); // 设置实体类包路径factory.setDataSource(dataSource);Map jpaProperties = new HashMap<>();jpaProperties.put("hibernate.hbm2ddl.auto", "update"); // 根据需要修改factory.setJpaPropertyMap(jpaProperties);return factory;}
}@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "secondaryEntityManagerFactory",transactionManagerRef = "secondaryTransactionManager",basePackages = {"com.example.secondary"} // 设置 secondary 数据源对应的 Repository 包路径
)
public class SecondaryJpaConfig {@Bean(name = "secondaryEntityManagerFactory")public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(@Qualifier("secondaryDataSource") DataSource dataSource) {return buildEntityManagerFactory(dataSource, "com.example.secondary"); // 使用 secondary 数据源对应的实体类包路径}@Bean(name = "secondaryTransactionManager")public PlatformTransactionManager secondaryTransactionManager(@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {return new JpaTransactionManager(entityManagerFactory);}// ... (如果使用和PrimaryJpaConfig相同的 buildEntityManagerFactory 方法, 可以将其提取到一个公共的工具类中)
}```
关键点:
`@Primary` 注解:标记主数据源,如果没有指定,Spring Boot 会自动选择一个。
`basePackages` 属性:指定每个数据源对应的 Repository 接口所在的包路径.
`packagesToScan` : 指定每个数据源对应的 Entity 实体类所在的包路径.### 4. 使用数据源在 Repository 接口或 Service 类中,可以使用 `@Qualifier` 注解指定要使用的数据源:```java
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;@Service
public class MyService {@PersistenceContext(unitName = "primaryEntityManagerFactory") // 指定 primary 数据源的 EntityManagerprivate EntityManager primaryEntityManager;@PersistenceContext(unitName = "secondaryEntityManagerFactory") // 指定 secondary 数据源的 EntityManagerprivate EntityManager secondaryEntityManager;@Autowired@Qualifier("primaryDataSource")private DataSource primaryDataSource;@Autowired@Qualifier("secondaryDataSource")private DataSource secondaryDataSource;// ... 使用 EntityManager 或 DataSource 进行数据库操作
}
```通过以上步骤,就可以在 Spring Boot 应用中配置和使用多个数据源了。 记住要根据你的具体需求调整配置,例如数据库类型、连接池参数、JPA 实现等。 仔细检查包路径和 `@Qualifier` 注解,确保正确地连接到对应的数据源。
Spring Boot 配置多数据源**简介**在实际开发中,我们常常需要连接多个数据库,例如读写分离、连接不同类型的数据库等。Spring Boot 提供了便捷的方式来配置多数据源,本文将详细介绍如何在 Spring Boot 应用中配置多个数据源。
1. 添加依赖首先,确保你的项目中包含了 Spring Boot Starter Data JPA 和所需数据库的驱动依赖。例如,如果你要连接 MySQL 和 PostgreSQL 数据库,需要添加以下依赖:```xml
org.springframework.bootspring-boot-starter-data-jpa
mysqlmysql-connector-javaruntime
org.postgresqlpostgresqlruntime
```
2. 配置多数据源Spring Boot 提供了多种方式配置多数据源,这里介绍两种常用的方式:
2.1 基于`@ConfigurationProperties`的配置方式这种方式比较简洁直观,适合简单的多数据源配置。1. 创建数据源配置类:```java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;@Configuration
public class DataSourceConfig {@Bean(name = "primaryDataSource")@Primary // 设置为主数据源@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();}
}
```2. 在 `application.properties` 或 `application.yml` 文件中配置数据库连接信息:```properties
spring.datasource.primary.url=jdbc:mysql://localhost:3306/primary_db
spring.datasource.primary.username=root
spring.datasource.primary.password=password
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.secondary.url=jdbc:postgresql://localhost:5432/secondary_db
spring.datasource.secondary.username=postgres
spring.datasource.secondary.password=password
spring.datasource.secondary.driver-class-name=org.postgresql.Driver
```
2.2 基于`DataSourceBuilder`的配置方式 (更灵活)这种方式更加灵活,可以自定义更多的数据源配置,例如连接池等。```java
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;@Configuration
public class DataSourceConfig {@Bean(name = "primaryDataSource")@Primarypublic DataSource primaryDataSource() {DataSourceBuilder> dataSourceBuilder = DataSourceBuilder.create();dataSourceBuilder.driverClassName("com.mysql.cj.jdbc.Driver");dataSourceBuilder.url("jdbc:mysql://localhost:3306/primary_db");dataSourceBuilder.username("root");dataSourceBuilder.password("password");return dataSourceBuilder.build();}@Bean(name = "secondaryDataSource")public DataSource secondaryDataSource() {DataSourceBuilder> dataSourceBuilder = DataSourceBuilder.create();dataSourceBuilder.driverClassName("org.postgresql.Driver");dataSourceBuilder.url("jdbc:postgresql://localhost:5432/secondary_db");dataSourceBuilder.username("postgres");dataSourceBuilder.password("password");return dataSourceBuilder.build();}
}
```
3. 配置`EntityManagerFactory` 和 `JpaTransactionManager`为每个数据源配置对应的 `EntityManagerFactory` 和 `JpaTransactionManager`:```java
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "primaryEntityManagerFactory",transactionManagerRef = "primaryTransactionManager",basePackages = {"com.example.primary"} // 设置 primary 数据源对应的 Repository 包路径
)
public class PrimaryJpaConfig {@Bean(name = "primaryEntityManagerFactory")public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(@Qualifier("primaryDataSource") DataSource dataSource) {return buildEntityManagerFactory(dataSource, "com.example.primary"); // 使用 primary 数据源对应的实体类包路径}@Bean(name = "primaryTransactionManager")public PlatformTransactionManager primaryTransactionManager(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {return new JpaTransactionManager(entityManagerFactory);}// ... 同样的方式配置 secondary 数据源private LocalContainerEntityManagerFactoryBean buildEntityManagerFactory(DataSource dataSource, String packageName) {HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();vendorAdapter.setGenerateDdl(true);LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();factory.setJpaVendorAdapter(vendorAdapter);factory.setPackagesToScan(packageName); // 设置实体类包路径factory.setDataSource(dataSource);Map jpaProperties = new HashMap<>();jpaProperties.put("hibernate.hbm2ddl.auto", "update"); // 根据需要修改factory.setJpaPropertyMap(jpaProperties);return factory;}
}@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "secondaryEntityManagerFactory",transactionManagerRef = "secondaryTransactionManager",basePackages = {"com.example.secondary"} // 设置 secondary 数据源对应的 Repository 包路径
)
public class SecondaryJpaConfig {@Bean(name = "secondaryEntityManagerFactory")public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(@Qualifier("secondaryDataSource") DataSource dataSource) {return buildEntityManagerFactory(dataSource, "com.example.secondary"); // 使用 secondary 数据源对应的实体类包路径}@Bean(name = "secondaryTransactionManager")public PlatformTransactionManager secondaryTransactionManager(@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {return new JpaTransactionManager(entityManagerFactory);}// ... (如果使用和PrimaryJpaConfig相同的 buildEntityManagerFactory 方法, 可以将其提取到一个公共的工具类中)
}```**关键点:*** `@Primary` 注解:标记主数据源,如果没有指定,Spring Boot 会自动选择一个。
* `basePackages` 属性:指定每个数据源对应的 Repository 接口所在的包路径.
* `packagesToScan` : 指定每个数据源对应的 Entity 实体类所在的包路径.
4. 使用数据源在 Repository 接口或 Service 类中,可以使用 `@Qualifier` 注解指定要使用的数据源:```java
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;@Service
public class MyService {@PersistenceContext(unitName = "primaryEntityManagerFactory") // 指定 primary 数据源的 EntityManagerprivate EntityManager primaryEntityManager;@PersistenceContext(unitName = "secondaryEntityManagerFactory") // 指定 secondary 数据源的 EntityManagerprivate EntityManager secondaryEntityManager;@Autowired@Qualifier("primaryDataSource")private DataSource primaryDataSource;@Autowired@Qualifier("secondaryDataSource")private DataSource secondaryDataSource;// ... 使用 EntityManager 或 DataSource 进行数据库操作
}
```通过以上步骤,就可以在 Spring Boot 应用中配置和使用多个数据源了。 记住要根据你的具体需求调整配置,例如数据库类型、连接池参数、JPA 实现等。 仔细检查包路径和 `@Qualifier` 注解,确保正确地连接到对应的数据源。