Java中的多資料來源管理:如何在單個應用中整合多資料庫
大家好,我是微賺淘客返利系統3.0的小編,是個冬天不穿秋褲,天冷也要風度的程式猿!在現代軟體架構中,應用往往需要訪問多個資料庫以支援不同的業務需求。本文將介紹如何在Java應用中實現多資料來源管理,包括配置、使用和切換資料來源的最佳實踐。
一、多資料來源的需求分析
多資料來源管理的需求通常來自以下幾種場景:
- 分離讀寫操作:為了提高效能,主庫用於寫操作,從庫用於讀操作。
- 不同的資料庫型別:例如,關係型資料庫與NoSQL資料庫的組合。
- 微服務架構:每個微服務可能使用獨立的資料來源。
二、技術棧選擇
在實現多資料來源管理時,以下技術棧是常見的選擇:
- Spring Boot:用於簡化應用的配置和開發。
- Spring Data JPA:提供統一的資料訪問層。
- HikariCP:高效能的JDBC連線池。
三、配置多資料來源
首先,確保你的pom.xml
中新增必要的依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
接下來,在application.yml
中配置多個資料來源:
spring:
datasource:
primary:
jdbc-url: jdbc:mysql://localhost:3306/primary_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 10
secondary:
jdbc-url: jdbc:mysql://localhost:3306/secondary_db
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 10
四、資料來源配置類
建立一個配置類,定義資料來源和實體管理器:
package cn.juwatech.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import javax.sql.DataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
@Configuration
@EnableJpaRepositories(
basePackages = "cn.juwatech.repository.primary",
entityManagerFactoryRef = "primaryEntityManagerFactory",
transactionManagerRef = "primaryTransactionManager"
)
public class PrimaryDataSourceConfig {
@Primary
@Bean(name = "primaryDataSource")
@ConfigurationProperties("spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Primary
@Bean(name = "primaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(primaryDataSource())
.packages("cn.juwatech.entity.primary")
.persistenceUnit("primary")
.build();
}
@Primary
@Bean(name = "primaryTransactionManager")
public DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
再建立一個類似的配置類用於配置第二個資料來源:
package cn.juwatech.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@EnableJpaRepositories(
basePackages = "cn.juwatech.repository.secondary",
entityManagerFactoryRef = "secondaryEntityManagerFactory",
transactionManagerRef = "secondaryTransactionManager"
)
public class SecondaryDataSourceConfig {
@Bean(name = "secondaryDataSource")
@ConfigurationProperties("spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondaryEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(secondaryDataSource())
.packages("cn.juwatech.entity.secondary")
.persistenceUnit("secondary")
.build();
}
@Bean(name = "secondaryTransactionManager")
public DataSourceTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
五、實體類與倉庫介面
根據資料來源建立不同的實體類和倉庫介面。以下是一個主資料來源的實體類及其對應的倉庫:
package cn.juwatech.entity.primary;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class PrimaryEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// Getters and Setters
}
對應的倉庫介面:
package cn.juwatech.repository.primary;
import cn.juwatech.entity.primary.PrimaryEntity;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PrimaryEntityRepository extends JpaRepository<PrimaryEntity, Long> {
}
同樣地,為第二個資料來源的實體類和倉庫定義類似的類。
六、服務層的實現
在服務層中,我們可以根據需求選擇不同的資料來源進行操作。以下是一個服務類示例:
package cn.juwatech.service;
import cn.juwatech.entity.primary.PrimaryEntity;
import cn.juwatech.entity.secondary.SecondaryEntity;
import cn.juwatech.repository.primary.PrimaryEntityRepository;
import cn.juwatech.repository.secondary.SecondaryEntityRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MultiDataSourceService {
@Autowired
private PrimaryEntityRepository primaryEntityRepository;
@Autowired
private SecondaryEntityRepository secondaryEntityRepository;
public PrimaryEntity savePrimaryEntity(PrimaryEntity entity) {
return primaryEntityRepository.save(entity);
}
public SecondaryEntity saveSecondaryEntity(SecondaryEntity entity) {
return secondaryEntityRepository.save(entity);
}
}
七、控制器的實現
最後,在控制器中實現對服務的呼叫:
package cn.juwatech.controller;
import cn.juwatech.entity.primary.PrimaryEntity;
import cn.juwatech.entity.secondary.SecondaryEntity;
import cn.juwatech.service.MultiDataSourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
public class MultiDataSourceController {
@Autowired
private MultiDataSourceService multiDataSourceService;
@PostMapping("/primary")
public PrimaryEntity createPrimary(@RequestBody PrimaryEntity entity) {
return multiDataSourceService.savePrimaryEntity(entity);
}
@PostMapping("/secondary")
public SecondaryEntity createSecondary(@RequestBody SecondaryEntity entity) {
return multiDataSourceService.saveSecondaryEntity(entity);
}
}
八、測試與驗證
可以使用Postman或其他工具測試API,驗證是否能夠成功操作不同資料來源的資料。
- 向
/api/primary
傳送POST請求,資料將儲存到主資料庫。 - 向
/api/secondary
傳送POST請求,資料將儲存到第二資料庫。
總結
透過以上步驟,我們成功地在Java應用中實現了多資料來源管理。可以根據業務需求擴充套件此方案,例如使用不同型別的資料庫,或者在微服務架構中靈活切換資料來源。藉助Spring Boot的強大功能和靈活配置,我們可以輕鬆管理和訪問多個資料庫,為複雜應用提供強有力的支援。
本文著作權歸聚娃科技微賺淘客系統開發者團隊,轉載請註明出處!