成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

數(shù)據(jù)庫(kù)
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ù)庫(kù)連接包,配置數(shù)據(jù)庫(kù)連接即可實(shí)現(xiàn)與數(shù)據(jù)庫(kù)通信。

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

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

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

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

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

3.支持多個(gè)數(shù)據(jù)庫(kù)來(lái)模擬各種自動(dòng)化測(cè)試場(chǎng)景。不同數(shù)據(jù)庫(kù)可能具有不同的配置和靜態(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ù)庫(kù)。

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

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ù)庫(kù)配置。

首先,在 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ù)庫(kù)
    @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ù)庫(kù)配置。

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

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

接下來(lái),我們還需要一個(gè)DBContextHolder類來(lái)保存數(shù)據(jù)庫(kù)引用并在運(yùn)行時(shí)動(dòng)態(tài)更改數(shù)據(jù)庫(kù)。

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
}

接下來(lái)我們需要對(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ù)庫(kù)。

好了,我們的配置就完成了。接下來(lái),我們測(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ù)庫(kù)名稱(db1、db2 或 db3)設(shè)置要指向的數(shù)據(jù)庫(kù)。

最后,編寫 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ù)源框架,也可以引入第三方庫(kù)來(lái)解決此需求。

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

2020-12-31 07:55:33

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

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ù)庫(kù)JDBC

2022-09-22 13:28:34

Redis分布式鎖

2022-09-29 08:28:57

SpringRedis分布式

2025-04-14 01:00:00

Calcite電商系統(tǒng)MySQL

2023-06-07 08:08:37

MybatisSpringBoot

2025-02-05 09:17:40

2023-10-31 07:52:53

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

2020-06-02 07:55:31

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

2023-01-04 09:33:31

SpringBootMybatis

2023-12-13 12:20:36

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

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

主站蜘蛛池模板: 99久久99| 精品美女 | 亚洲精品久久久久avwww潮水 | 中文字幕 欧美 日韩 | 国产精品污www一区二区三区 | 午夜欧美 | 欧美中文字幕一区二区三区亚洲 | 久久精品一区二区三区四区 | 免费观看的av毛片的网站 | 黄一级| 国产午夜精品一区二区三区嫩草 | 国产日韩一区二区三免费 | 一级aaaa毛片 | 久久中文字幕av | 欧美成人免费在线 | 欧美一区二区在线观看 | 国产成人精品免高潮在线观看 | 99久久婷婷国产精品综合 | 欧美国产精品久久久 | 日本免费一区二区三区四区 | 国产一级大片 | 欧美日韩国产一区二区三区 | 久久久人成影片免费观看 | 欧美一区二区三区,视频 | 人人亚洲 | 国产精品久久久久久久久久久久久久 | 日韩高清一区 | 精品精品视频 | 99国内精品久久久久久久 | 毛片一级网站 | 国产精品一区网站 | 91一区二区 | 亚洲高清在线 | 91精品久久久久久久久中文字幕 | 久久夜色精品国产 | 亚洲精品视频在线看 | 九九九久久国产免费 | 免费在线观看h片 | 精品一区国产 | 亚洲欧美在线一区 | 欧美lesbianxxxxhd视频社区 |