最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot如何設(shè)置多數(shù)據(jù)源,隨時(shí)切換

 更新時(shí)間:2024年04月01日 15:57:56   作者:快樂敲代碼  
這篇文章主要介紹了Springboot如何設(shè)置多數(shù)據(jù)源,隨時(shí)切換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

需求

接到一個(gè)任務(wù),把一個(gè)數(shù)據(jù)庫(kù)里面的數(shù)據(jù)定時(shí)導(dǎo)入到另外的數(shù)據(jù)庫(kù)中

但是又不允許我們通過(guò)binlog+canal同步,所以考慮起一個(gè)微服務(wù)充當(dāng)同步腳本的作用

且配置多數(shù)據(jù)庫(kù),并且支持隨時(shí)切換

環(huán)境

  • 1、mysql多個(gè)庫(kù)
  • 2、mysql+postgresql

思路

spring框架本身支持多數(shù)據(jù)源,我們查看他的定義

Spring的多數(shù)據(jù)源支持—AbstractRoutingDataSource,AbstractRoutingDataSource定義了抽象的determineCurrentLookupKey方法,子類實(shí)現(xiàn)此方法,來(lái)確定要使用的數(shù)據(jù)源

看下下面它的源碼:

public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
	 protected DataSource determineTargetDataSource() {
		Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
		Object lookupKey = determineCurrentLookupKey();
		DataSource dataSource = this.resolvedDataSources.get(lookupKey);
		if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
			dataSource = this.resolvedDefaultDataSource;
		}
		if (dataSource == null) {
			throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
		}
		return dataSource;
	}

        // 確定當(dāng)前要使用的數(shù)據(jù)源
        protected abstract Object determineCurrentLookupKey();
}

所以我們只要寫一個(gè)自定義類去繼承上面這個(gè)AbstractRoutingDataSource類,并重寫determineCurrentLookupKey 方法即可

操作

包如下:

一、多個(gè)庫(kù)都是mysql類型

pom依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.7</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>db-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>db-demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

1、配置文件application.yml

#端口
server.port: 7788
spring.application.name: bddemo

# mysql
spring.datasource:
  driver-class-name: com.mysql.cj.jdbc.Driver
  #數(shù)據(jù)庫(kù)1
  db1:
    jdbc-url: jdbc:mysql://127.0.0.1:3306/db1?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: 123456
  #數(shù)據(jù)庫(kù)2
  db2:
    jdbc-url: jdbc:mysql://127.0.0.1:3306/db2?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: 123456

# mybatis
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
  type-aliases-package: ccom.example.demo.*.entity

2、配置類

1) DataSourceConfig 數(shù)據(jù)庫(kù)配置類:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* 數(shù)據(jù)庫(kù)配置
* @date 2022/5/19
*/
@Configuration
public class DataSourceConfig {

    /**
     * 數(shù)據(jù)源1
     * spring.datasource.db1:application.properteis中對(duì)應(yīng)屬性的前綴
     * @return
     */
    @Bean(name = "db1")
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public DataSource dataSourceOne() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 數(shù)據(jù)源2
     * spring.datasource.db2:application.properteis中對(duì)應(yīng)屬性的前綴
     * @return
     */
    @Bean(name = "db2")
    @ConfigurationProperties(prefix = "spring.datasource.db2")
    public DataSource dataSourceTwo() {
        return DataSourceBuilder.create().build();
    }

    /**
     * 動(dòng)態(tài)數(shù)據(jù)源: 通過(guò)AOP在不同數(shù)據(jù)源之間動(dòng)態(tài)切換
     * @return
     */
    @Primary
    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 默認(rèn)數(shù)據(jù)源
        dynamicDataSource.setDefaultTargetDataSource(dataSourceOne());
        // 配置多數(shù)據(jù)源
        Map<Object, Object> dsMap = new HashMap<>();
        dsMap.put("db1", dataSourceOne());
        dsMap.put("db2", dataSourceTwo());

        dynamicDataSource.setTargetDataSources(dsMap);
        return dynamicDataSource;
    }

    /**
     * 配置多數(shù)據(jù)源后IOC中存在多個(gè)數(shù)據(jù)源了,事務(wù)管理器需要重新配置,不然器不知道選擇哪個(gè)數(shù)據(jù)源
     * 事務(wù)管理器此時(shí)管理的數(shù)據(jù)源將是動(dòng)態(tài)數(shù)據(jù)源dynamicDataSource
     * 配置@Transactional注解
     * @return
     */
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dynamicDataSource());
    }
}

2) DynamicDataSource 動(dòng)態(tài)數(shù)據(jù)源類:

import com.example.demo.utils.DataSourceUtil;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
 * 動(dòng)態(tài)數(shù)據(jù)源類
 * @date 2022/2/11
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceUtil.getDB();
    }
}

3、切換工具類:DataSourceUtil

/**
* 數(shù)據(jù)源切換工具
 * @date 2022/5/19
*/
public class DataSourceUtil {
    /**
     * 默認(rèn)數(shù)據(jù)源
     */
    public static final String DEFAULT_DS = "db1";
    /**
    *  數(shù)據(jù)源屬于一個(gè)公共的資源
    *  采用ThreadLocal可以保證在多線程情況下線程隔離
    */
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    /**
     * 設(shè)置數(shù)據(jù)源名
     * @param dbType
     */
    public static void setDB(String dbType) {
        contextHolder.set(dbType);
    }

    /**
     * 獲取數(shù)據(jù)源名
     * @return
     */
    public static String getDB() {
        return (contextHolder.get());
    }

    /**
     * 清除數(shù)據(jù)源名
     */
    public static void clearDB() {
        contextHolder.remove();
    }
}

4、啟動(dòng)

(1)啟動(dòng)類中配置移除默認(rèn)的數(shù)據(jù)庫(kù)配置類

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

//移除默認(rèn)數(shù)據(jù)庫(kù)配置類
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class DbDemoApplication {

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

}

(2)測(cè)試

結(jié)果

  • db1庫(kù)

  • db2庫(kù)

二、一個(gè)是mysql一個(gè)是postgresql

1、pom依賴新增

    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <scope>runtime</scope>
    </dependency>

2、配置文件application.yml

#端口
server.port: 7788
spring.application.name: bddemo

# mysql
spring.datasource:
  #數(shù)據(jù)庫(kù)1
  db1:
    driver-class-name: com.mysql.cj.jdbc.Driver
    jdbc-url: jdbc:mysql://127.0.0.1:3306/db1?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: 123456
  #數(shù)據(jù)庫(kù)2
  db2:
#    driver-class-name: com.mysql.cj.jdbc.Driver
#    jdbc-url: jdbc:mysql://127.0.0.1:3306/db2?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
#    username: root
#    password: 123456
    driver-class-name: org.postgresql.Driver
    jdbc-url: jdbc:postgresql://127.0.0.1:5432/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&useSSL=false
    username: postgres
    password: 123456

# mybatis
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml
  type-aliases-package: ccom.example.demo.*.entity

注意:

之前都是mysql的庫(kù),所以驅(qū)動(dòng)在上面

現(xiàn)在因?yàn)閿?shù)據(jù)庫(kù)的產(chǎn)品不一樣,所以驅(qū)動(dòng)類名稱放在下面單獨(dú)配置(有些人真完全不會(huì)變通,哎)

3、測(cè)試

插入:pg數(shù)據(jù)庫(kù)的主鍵自增mybatis還有點(diǎn)難搞,我們直接配置id插入

  • mysql:

  • pg:

  • 查詢:

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Eclipse中創(chuàng)建Web項(xiàng)目最新方法(2023年)

    Eclipse中創(chuàng)建Web項(xiàng)目最新方法(2023年)

    在Java開發(fā)人員中,最常用的開發(fā)工具應(yīng)該就是Eclipse,下面這篇文章主要給大家介紹了關(guān)于Eclipse中創(chuàng)建Web項(xiàng)目2023年最新的方法,需要的朋友可以參考下
    2023-09-09
  • Java 內(nèi)存模型 (JMM) 與 volatile 底層實(shí)現(xiàn)

    Java 內(nèi)存模型 (JMM) 與 volatile 底層實(shí)現(xiàn)

    這篇文章詳細(xì)介紹了Java中的volatile關(guān)鍵字,從硬件底層到JVM規(guī)范,逐步講解了它的核心原理,包括可見性和禁止重排序,文章還探討了volatile的使用場(chǎng)景、常見誤區(qū)以及在實(shí)際工作中的應(yīng)用,感興趣的朋友跟隨小編一起看看吧
    2026-03-03
  • IDEA配置JavaFX全過(guò)程

    IDEA配置JavaFX全過(guò)程

    從Java11起,Java不再內(nèi)置JavaFX,在Java17項(xiàng)目中,需手動(dòng)配置開發(fā)環(huán)境,添加JavaFX庫(kù)路徑,并設(shè)置運(yùn)行參數(shù)指向本地路徑
    2025-09-09
  • Java?基于Hutool實(shí)現(xiàn)DES加解密示例詳解

    Java?基于Hutool實(shí)現(xiàn)DES加解密示例詳解

    這篇文章主要介紹了Java基于Hutool實(shí)現(xiàn)DES加解密,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • JAVA強(qiáng)密碼校驗(yàn)算法示例代碼

    JAVA強(qiáng)密碼校驗(yàn)算法示例代碼

    最近系統(tǒng)需要做用戶密碼升級(jí),增加強(qiáng)密碼校驗(yàn),密碼長(zhǎng)度,復(fù)雜度等等,這篇文章主要介紹了JAVA強(qiáng)密碼校驗(yàn)算法的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-07-07
  • 淺談java+內(nèi)存分配及變量存儲(chǔ)位置的區(qū)別

    淺談java+內(nèi)存分配及變量存儲(chǔ)位置的區(qū)別

    下面小編就為大家?guī)?lái)一篇淺談java+內(nèi)存分配及變量存儲(chǔ)位置的區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-08-08
  • SpringBoot中的事務(wù)配置管理詳解

    SpringBoot中的事務(wù)配置管理詳解

    這篇文章主要介紹了SpringBoot中的事務(wù)配置管理詳解,Spring Boot 默認(rèn)的事務(wù)規(guī)則是遇到運(yùn)行異常(RuntimeException)和程序錯(cuò)誤(Error)才會(huì)回滾,但是拋出SQLException就無(wú)法回滾了,需要的朋友可以參考下
    2024-01-01
  • java反射之獲取類的信息方法(推薦)

    java反射之獲取類的信息方法(推薦)

    下面小編就為大家?guī)?lái)一篇java反射之獲取類的信息方法(推薦)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • idea中使用(Revert Commit)圖解

    idea中使用(Revert Commit)圖解

    這篇文章主要介紹了idea中使用(Revert Commit)圖解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • eclipse下搭建hibernate5.0環(huán)境的步驟(圖文)

    eclipse下搭建hibernate5.0環(huán)境的步驟(圖文)

    這篇文章主要介紹了eclipse下搭建hibernate5.0環(huán)境的步驟(圖文),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-05-05

最新評(píng)論

常州市| 黄陵县| 喀喇| 嵩明县| 湾仔区| 柳河县| 鄢陵县| 恩施市| 郓城县| 太仓市| 大兴区| 云阳县| 凤台县| 东宁县| 华阴市| 洛阳市| 晋城| 江川县| 灵宝市| 桃源县| 报价| 宕昌县| 浑源县| 田林县| 深水埗区| 榆树市| 屏南县| 登封市| 拜泉县| 英山县| 汉川市| 曲阜市| 陕西省| 华宁县| 亳州市| 南岸区| 屯昌县| 长沙县| 鹤岗市| 凤山县| 开远市|