自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

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

Spring Boot 提供了 Data JPA 的包,允許你使用類似 ORM 的接口連接到 RDMS。它很容易使用和實(shí)現(xiàn),只需要在 pom.xml 中添加一個(gè)條目(如果使用的是 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 個(gè)注釋:

@SpringBootApplication
@EnableJpaRepositories
@EnableAutoConfiguration
public class SpringMainApplication {

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

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

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

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

多數(shù)據(jù)源有哪些應(yīng)用場(chǎng)景?

1.支持具有相同模式的同一應(yīng)用程序內(nèi)的多租戶。

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

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

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

5.一次性為多個(gè)數(shù)據(jù)庫插入數(shù)據(jù)。例如,你有一個(gè)從腳本創(chuàng)建數(shù)據(jù)的批處理作業(yè),你可以一次性連接到多個(gè)數(shù)據(jù)庫,并對(duì)所有這些數(shù)據(jù)庫運(yùn)行腳本,而無需指向不同的應(yīng)用程序或重新啟動(dòng)服務(wù)器來執(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 個(gè)獨(dú)立的 PostgresSQL 實(shí)例,具有相同的模式但具有不同的數(shù)據(jù)。

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

首先,在 Spring 應(yīng)用程序主文件中添加注解:

@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 實(shí)體路徑
    private final String PACKAGE_SCAN = "com.sample.client.repositories.dto.entity";

    // 將db1設(shè)置為主數(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;
    }

    //多實(shí)體配置代碼
    @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 個(gè)數(shù)據(jù)庫通用的 JPA 實(shí)體。

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

接下來,我們還需要一個(gè)DBContextHolder類來保存數(shù)據(jù)庫引用并在運(yùn)行時(shí)動(dòng)態(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
}

接下來我們需要對(duì)MultiRoutingDataSource進(jìn)行重寫

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

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

好了,我們的配置就完成了。接下來,我們測(cè)試下多數(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實(shí)現(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 端點(diǎn)傳入的數(shù)據(jù)庫名稱(db1、db2 或 db3)設(shè)置要指向的數(shù)據(jù)庫。

最后,編寫 JPA Repository 基礎(chǔ)代碼:

@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; 
}

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

總結(jié)

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

責(zé)任編輯:華軒 來源: 今日頭條
相關(guān)推薦

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

微服務(wù)數(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-29 08:28:57

SpringRedis分布式

2022-09-22 13:28:34

Redis分布式鎖

2023-06-07 08:08:37

MybatisSpringBoot

2025-02-05 09:17:40

2020-06-02 07:55:31

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

2023-10-31 07:52:53

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

2023-01-04 09:33:31

SpringBootMybatis

2023-12-13 12:20:36

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

51CTO技術(shù)棧公眾號(hào)