Java中的多資料來源管理:如何在單個應用中整合多資料庫

省赚客开发者团队發表於2024-09-21

Java中的多資料來源管理:如何在單個應用中整合多資料庫

大家好,我是微賺淘客返利系統3.0的小編,是個冬天不穿秋褲,天冷也要風度的程式猿!在現代軟體架構中,應用往往需要訪問多個資料庫以支援不同的業務需求。本文將介紹如何在Java應用中實現多資料來源管理,包括配置、使用和切換資料來源的最佳實踐。

一、多資料來源的需求分析

多資料來源管理的需求通常來自以下幾種場景:

  1. 分離讀寫操作:為了提高效能,主庫用於寫操作,從庫用於讀操作。
  2. 不同的資料庫型別:例如,關係型資料庫與NoSQL資料庫的組合。
  3. 微服務架構:每個微服務可能使用獨立的資料來源。

二、技術棧選擇

在實現多資料來源管理時,以下技術棧是常見的選擇:

  • 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,驗證是否能夠成功操作不同資料來源的資料。

  1. /api/primary傳送POST請求,資料將儲存到主資料庫。
  2. /api/secondary傳送POST請求,資料將儲存到第二資料庫。

總結

透過以上步驟,我們成功地在Java應用中實現了多資料來源管理。可以根據業務需求擴充套件此方案,例如使用不同型別的資料庫,或者在微服務架構中靈活切換資料來源。藉助Spring Boot的強大功能和靈活配置,我們可以輕鬆管理和訪問多個資料庫,為複雜應用提供強有力的支援。

本文著作權歸聚娃科技微賺淘客系統開發者團隊,轉載請註明出處!

相關文章