偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

基于Spring boot輕松實現(xiàn)一個多數(shù)據(jù)源框架

數(shù)據(jù)庫
Spring Boot 提供了 Data JPA 的包,允許你使用類似 ORM 的接口連接到 RDMS。它很容易使用和實現(xiàn),只需要在 pom.xml 中添加一個條目(如果使用的是 Maven,Gradle 則是在 build.gradle 文件中)。

Spring Boot 提供了 Data JPA 的包,允許你使用類似 ORM 的接口連接到 RDMS。它很容易使用和實現(xiàn),只需要在 pom.xml 中添加一個條目(如果使用的是 Maven,Gradle 則是在 build.gradle 文件中)。

<dependencies>
        <!-- Spring boot 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency> 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
</dependencies>

在Main Spring Application類中添加 2 個注釋:

@SpringBootApplication
@EnableJpaRepositories
@EnableAutoConfiguration
public class SpringMainApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringMainApplication.class, args);
    }
}

最后添加一個數(shù)據(jù)庫連接包,配置數(shù)據(jù)庫連接即可實現(xiàn)與數(shù)據(jù)庫通信。

接下來,我們開始配置多數(shù)據(jù)源連接。

注意:多個數(shù)據(jù)庫應該具有相同的驅動程序。無法連接到不同的數(shù)據(jù)庫,如 MySql 和 Postgres SQL 數(shù)據(jù)庫。數(shù)據(jù)庫必須相同。此外,數(shù)據(jù)庫模式必須相同,不同模式的 2 個數(shù)據(jù)庫無法進行連接。

多數(shù)據(jù)源有哪些應用場景?

1.支持具有相同模式的同一應用程序內的多租戶。

2.動態(tài)模擬多個環(huán)境數(shù)據(jù)庫上的行為 ,而不需要重新啟動應用程序。 例如,你可以動態(tài)連接到開發(fā)數(shù)據(jù)庫或 QA 數(shù)據(jù)庫,而無需重新啟動應用程序。

3.支持多個數(shù)據(jù)庫來模擬各種自動化測試場景。不同數(shù)據(jù)庫可能具有不同的配置和靜態(tài)信息,意味著你可以用一個自動化測試腳本覆蓋多個測試用例。

4.在同一個應用程序中支持多個組織。根據(jù)用戶登錄,可以動態(tài)決定他們的數(shù)據(jù)應進入哪個組織的數(shù)據(jù)庫。

5.一次性為多個數(shù)據(jù)庫插入數(shù)據(jù)。例如,你有一個從腳本創(chuàng)建數(shù)據(jù)的批處理作業(yè),你可以一次性連接到多個數(shù)據(jù)庫,并對所有這些數(shù)據(jù)庫運行腳本,而無需指向不同的應用程序或重新啟動服務器來執(zhí)行此操作。

多數(shù)據(jù)源示意圖如下:

第一步:添加 pom 依賴

<dependencies>
        <!-- Spring boot dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Swagger dependencies -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

        <!-- lombok dependency -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>

        <!-- Database dependency -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
        </dependency>


        <!-- test dependencies -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-parent</artifactId>
                <version>${spring-cloud-dependencies.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-gcp-dependencies</artifactId>
                <version>${project.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

第二步:添加數(shù)據(jù)庫連接配置

app.datasource.db1.jdbc-url=jdbc:postgresql://db1.com:5432/dbname1
app.datasource.db1.username=postgres
app.datasource.db1.password=password

app.datasource.db2.jdbc-url=jdbc:postgresql://db2.com:5432/dbname2
app.datasource.db2.username=postgres
app.datasource.db2.password=password

app.datasource.db3.jdbc-url=jdbc:postgresql://db3.com:5432/dbname3
app.datasource.db3.username=postgres
app.datasource.db3.password=password

這是 3 個獨立的 PostgresSQL 實例,具有相同的模式但具有不同的數(shù)據(jù)。

第三步:添加多數(shù)據(jù)庫配置。

首先,在 Spring 應用程序主文件中添加注解:

@SpringBootApplication
@EnableJpaRepositories
@EnableAutoConfiguration
public class MultidatabaseApplication {

    public static void main(String[] args) {
        SpringApplication.run(MultidatabaseApplication.class, args);
    }
}

添加配置類:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "multiEntityManager",
        transactionManagerRef = "multiTransactionManager")
@EntityScan("com.sample.client.repositories.dto.entity")
public class DatabaseConfiguration {
    //添加 JPA 實體路徑
    private final String PACKAGE_SCAN = "com.sample.client.repositories.dto.entity";

    // 將db1設置為主數(shù)據(jù)庫
    @Primary
    @Bean(name = "db1DataSource")
    @ConfigurationProperties("app.datasource.db1")
    public DataSource db1DataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    //db2連接數(shù)據(jù)源注入
    @Bean(name = "db2DataSource")
    @ConfigurationProperties("app.datasource.db2")
    public DataSource db2DataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }
    //db3連接數(shù)據(jù)源注入
    @Bean(name = "db3DataSource")
    @ConfigurationProperties("app.datasource.db3")
    public DataSource db3DataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }

    //多數(shù)據(jù)源配置
    @Bean(name = "multiRoutingDataSource")
    public DataSource multiRoutingDataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(ClientNames.DB1, db1DataSource());
        targetDataSources.put(ClientNames.DB2, db2DataSource());
        targetDataSources.put(ClientNames.DB3, db3DataSource());
        MultiRoutingDataSource multiRoutingDataSource 
            = new MultiRoutingDataSource();
        multiRoutingDataSource.setDefaultTargetDataSource(db1DataSource());
        multiRoutingDataSource.setTargetDataSources(targetDataSources);
        return multiRoutingDataSource;
    }

    //多實體配置代碼
    @Bean(name = "multiEntityManager")
    public LocalContainerEntityManagerFactoryBean multiEntityManager() {
        LocalContainerEntityManagerFactoryBean em 
            = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(multiRoutingDataSource());
        em.setPackagesToScan(PACKAGE_SCAN);
        HibernateJpaVendorAdapter vendorAdapter 
            = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(hibernateProperties());
        return em;
    }

    @Bean(name = "multiTransactionManager")
    public PlatformTransactionManager multiTransactionManager() {
        JpaTransactionManager transactionManager
                = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(
                multiEntityManager().getObject());
        return transactionManager;
    }

    @Primary
    @Bean(name="entityManagerFactory")
    public LocalSessionFactoryBean dbSessionFactory() {
        LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
        sessionFactoryBean.setDataSource(multiRoutingDataSource());
        sessionFactoryBean.setPackagesToScan(PACKAGE_SCAN);
        sessionFactoryBean.setHibernateProperties(hibernateProperties());
        return sessionFactoryBean;
    }

    //添加 hibernate 屬性
    private Properties hibernateProperties() {
        Properties properties = new Properties();
        properties.put("hibernate.show_sql", true);
        properties.put("hibernate.format_sql", true);
        properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
        properties.put("hibernate.id.new_generator_mappings", false);
        properties.put("hibernate.jdbc.lob.non_contextual_creation", true);
        return properties;
    }
}

這樣就完成了我們的多數(shù)據(jù)庫配置。

com.sample.client.repositories.dto.entity — 此目錄包含 3 個數(shù)據(jù)庫通用的 JPA 實體。

MultiRoutingDataSource類是我們的實際實現(xiàn),允許我們連接到多個數(shù)據(jù)庫

接下來,我們還需要一個DBContextHolder類來保存數(shù)據(jù)庫引用并在運行時動態(tài)更改數(shù)據(jù)庫。

public class DBContextHolder {
    private static final ThreadLocal<ClientNames> contextHolder = new ThreadLocal<>();
    public static void setCurrentDb(ClientNames dbType) {
        contextHolder.set(dbType);
    }
    public static ClientNames getCurrentDb() {
        return contextHolder.get();
    }
    public static void clear() {
        contextHolder.remove();
    }
}

ClientNames枚舉類如下:

public enum ClientNames {
    DB1, DB2, DB3
}

接下來我們需要對MultiRoutingDataSource進行重寫

public class MultiRoutingDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DBContextHolder.getCurrentDb();
    }
}

determineCurrentLookupKey 方法用于決定應用程序應該動態(tài)連接到哪個數(shù)據(jù)庫。

好了,我們的配置就完成了。接下來,我們測試下多數(shù)據(jù)源是否生效:

@RestController
@RequestMapping("/client")
public class ClientDataController {

    @Autowired
    private ClientMasterService clientMasterService;

    @GetMapping("/{clientdb}")
    public String findFromDatabase(@PathVariable String clientdbName) {
        return clientMasterService.getClientNames(clientdbName);
    }
}

ClientMasterService實現(xiàn)如下:

@Service
public class ClientMasterService {

    @Autowired
    private ClientMasterRepository clientMasterRepository;

    public String getClientNames(String client) {
        switch (client) {
            case "db1":
                DBContextHolder.setCurrentDb(ClientNames.DB1);
                break;
            case "db2":
                DBContextHolder.setCurrentDb(ClientNames.DB2);
                break;
            case "db3":
                DBContextHolder.setCurrentDb(ClientNames.DB3);
                break;
        }
        Entity1 e1 = clientMasterRepository.findByEntity1Name("John Doe");
        if(e1 != null) {
            return "found in database: " + client + " with id " + e1.getId();
        }
        return "found in " + client + " nada!";
    }
}

ClientMasterService使用DBContextHolder類根據(jù)從 Rest 端點傳入的數(shù)據(jù)庫名稱(db1、db2 或 db3)設置要指向的數(shù)據(jù)庫。

最后,編寫 JPA Repository 基礎代碼:

@Repository
public interface ClientMasterRepository extends JpaRepository<Entity1, String> {
    Entity1 findByEntity1Name(String name);
}

Entity1 類如下:

@Entity
@Table(name = "entity1")
@Getter
@Setter
public class Entity1 implements Serializable {
  @Id
  @Column(name = "id", nullable = false)
  private Integer id;
    
  @Column(name = "entity1Name")
  private String entity1Name; 
}

這樣就完成了整個多數(shù)據(jù)源的配置?。?!

總結

如果你有多租戶需求,或者多環(huán)境測試需求等,可以自己嘗試編寫一個多數(shù)據(jù)源框架,也可以引入第三方庫來解決此需求。

責任編輯:華軒 來源: 今日頭條
相關推薦

2020-12-31 07:55:33

spring bootMybatis數(shù)據(jù)庫

2022-05-18 12:04:19

Mybatis數(shù)據(jù)源Spring

2020-11-24 09:56:12

數(shù)據(jù)源讀寫分離

2023-09-07 08:39:39

copy屬性數(shù)據(jù)源

2023-11-27 07:33:55

2022-06-02 10:38:42

微服務數(shù)據(jù)源分布式

2009-08-14 10:26:27

ibatis多數(shù)據(jù)源

2025-01-17 09:11:51

2021-03-10 19:01:02

SQL數(shù)據(jù)源

2024-10-30 10:22:17

2022-12-19 07:21:35

Hutool-db數(shù)據(jù)庫JDBC

2025-04-14 01:00:00

Calcite電商系統(tǒng)MySQL

2022-09-22 13:28:34

Redis分布式鎖

2022-09-29 08:28:57

SpringRedis分布式

2023-06-07 08:08:37

MybatisSpringBoot

2025-02-05 09:17:40

2023-01-04 09:33:31

SpringBootMybatis

2020-06-02 07:55:31

SpringBoot多數(shù)據(jù)源

2023-10-31 07:52:53

多數(shù)據(jù)源管理后端

2023-12-13 12:20:36

SpringMySQL數(shù)據(jù)源
點贊
收藏

51CTO技術棧公眾號