1. 介绍
在这个简短的教程中,我们将学习如何在Spring Boot应用程序中配置多个数据源。
想象一下,我们正在开发一个电子商务应用程序,并且需要两个独立的数据库来存储客户和订单。我们将把它们配置为独立的数据源,并看看如何在我们的应用程序中使用它们。
2. 配置属性
让我们先在 application.properties
中为我们的 Customer 和 Order 数据源定义一些属性:
#Customer db
spring.datasource.customer.url = [url]
spring.datasource.customer.username = [username]
spring.datasource.customer.password = [password]
spring.datasource.customer.driverClassName = org.postgresql.Driver
#Order db
spring.datasource.order.url = [url]
spring.datasource.order.username = [username]
spring.datasource.order.password = [password]
spring.datasource.order.driverClassName = org.sqlite.JDBC
在上面,我们定义了两个数据库的数据源及其各自的属性。此外,我们还可以配置不同类型的数据库。
现在,我们可以在应用程序中使用这些属性。
3. 配置数据源
接下来,我们将创建一个配置类,在其中为每个数据库定义两个 DataSource
bean:
@Configuration
public class CustomerOrderDataSourcesConfiguration {
@Primary
@Bean(name = "customerDataSource")
@ConfigurationProperties(prefix = "spring.datasource.customer")
public DataSource customerDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "orderDataSource")
@ConfigurationProperties(prefix = "spring.datasource.order")
public DataSource orderDataSource() {
return DataSourceBuilder.create().build();
}
}
我们明确命名我们的bean,以便可以通过@Qualifier
注解决定引用哪个数据源。此外,我们将customerDataSource
标记为@Primary
,并将其视为我们应用程序的主要数据库。因此,如果我们不使用@Qualifier
注解,Spring将在需要的地方注入客户数据源。
让我们看看如何使用这些beans。
4. 使用数据源
我们可以在应用程序中根据需要注入这两个数据源。
例如,我们可以使用 @Autowired
注解在服务类中注入数据源:
@Autowired
@Qualifier("orderDataSource")
private DataSource orderDataSource;
然而,大多数时候,我们希望将数据源连接到Spring Data JPA仓库,并使用它来代替直接与数据源交互。
接下来让我们看看如何配置。
5. 配置 @Repository
使用特定的数据源
首先,我们需要创建一个配置类,在其中使用 @EnableJpaRepositories
注解来扫描仓库,并为每个数据源定义实体管理器工厂:
@Configuration
@EnableJpaRepositories(
basePackages = "com.namastecode.repositories.customer",
entityManagerFactoryRef = "customerEntityManagerFactory",
transactionManagerRef = "customerTransactionManager"
)
public class CustomerDataSourceConfiguration{
// More code
}
现在,我们需要在这个类中创建 entityManagerFactory
bean:
@Primary
@Bean(name = "customerEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("customerDataSource") DataSource dataSource) {
return builder
.dataSource(dataSource)
.packages("com.namastecode.domain.customer") // entities package
.persistenceUnit("customers")
.build();
}
接下来,我们将创建 transactionManager
bean,以便每个数据源都有自己的事务管理器,并且不会相互冲突:
@Primary
@Bean(name = "customerTransactionManager")
public PlatformTransactionManager customerTransactionManager(
@Qualifier("customerEntityManagerFactory") EntityManagerFactory customerEntityManagerFactory) {
return new JpaTransactionManager(customerEntityManagerFactory);
}
在上面,我们将两个 bean 都定义为 @Primary
,因为客户数据源是默认的。对于订单数据源,我们不需要这样做。
我们已准备好在包 com.namastecode.domain.customer
下创建我们的实体:
@Entity
@Table(name = "customers")
public class Customer {
// More code
}
同样,我们可以在包 com.namastecode.repositories.customer
下创建这些仓库:
@Repository
public interface CustomerRepository extends JpaRepository<Customer, Long> {
// More code
}
现在,我们有两个独立的数据源及其资源。然而,可能会出现一种情况,我们希望配置数据源,以便在两个数据源之间使用单个事务。接下来,让我们看看如何做到这一点。
6. 配置一个链式事务管理器
如果我们想在两个数据源之间执行事务,我们可以设置一个 ChainedTransactionManager
bean,之后在我们的操作中可以使用:
@Bean(name = "chainedTransactionManager")
public ChainedTransactionManager chainedTransactionManager(
@Qualifier("customerTransactionManager") PlatformTransactionManager customerTransactionManager,
@Qualifier("orderTransactionManager") PlatformTransactionManager orderTransactionManager) {
return new ChainedTransactionManager(customerTransactionManager, orderTransactionManager);
}
接下来,假设我们有一个 CustomerOrderService
,在这里我们使用了 CustomerRepository
和 OrderRepository
。因此,为了在这个服务类中使用我们的链式事务管理器,我们可以显式地定义事务管理器:
@Service
public class CustomerOrderService {
@Autowired
private CustomerRepository customerRepository;
@Autowired
private OrderRepository orderRepository;
@Transactional(transactionManager = "chainedTransactionManager")
public void updateCustomerAndOrder(Customer customer, Order order) {
customerRepository.save(customer);
orderRepository.save(order);
}
}
上面,如果任何保存操作失败,事务将为这两个数据源回滚。
7. 结论
在本教程中,我们学习了如何在Spring Boot应用程序中配置多个数据源。
首先,我们定义了每个数据源的属性,创建了数据源 beans,使用特定的数据源配置了 @Repository
,最后,我们了解了如何为两个数据源配置共享的事务管理器。