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

springboot使用DynamicDataSource動態(tài)切換數(shù)據(jù)源的實現(xiàn)過程

 更新時間:2023年08月07日 10:00:44   作者:菜鳥的IT學(xué)習(xí)之路  
這篇文章主要給大家介紹了關(guān)于springboot使用DynamicDataSource動態(tài)切換數(shù)據(jù)源的實現(xiàn)過程,Spring Boot應(yīng)用中可以配置多個數(shù)據(jù)源,并根據(jù)注解靈活指定當(dāng)前使用的數(shù)據(jù)源,需要的朋友可以參考下

DynamicDataSource是一個數(shù)據(jù)源路由器,可以根據(jù)上下文動態(tài)選擇數(shù)據(jù)源??梢栽诿總€請求或線程中將數(shù)據(jù)源設(shè)置為當(dāng)前需要使用的數(shù)據(jù).

1. 創(chuàng)建一個DynamicDataSource類來實現(xiàn)數(shù)據(jù)源路由邏輯

創(chuàng)建一個DynamicDataSource類,它繼承自AbstractRoutingDataSource。在該類中重寫**determineCurrentLookupKey()**方法,該方法返回一個字符串,用于指示當(dāng)前要使用哪個數(shù)據(jù)源

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSourceName();
    }
    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }
}

2. 創(chuàng)建DynamicDataSourceContextHolder線程安全類

在多線程環(huán)境下,如果多個線程同時訪問同一個方法,并且每個線程要使用不同的數(shù)據(jù)源,那么就需要對數(shù)據(jù)源進(jìn)行動態(tài)切換。如果在方法中使用一個共享的變量來存儲當(dāng)前要使用的數(shù)據(jù)源名稱,那么就會存在線程安全問題,可能會導(dǎo)致不同線程之間的數(shù)據(jù)源切換混亂,或者數(shù)據(jù)源切換不成功的情況發(fā)生。

為了解決這個問題,可以使用ThreadLocal來存儲當(dāng)前要使用的數(shù)據(jù)源名稱。ThreadLocal是一種線程本地存儲機(jī)制,它可以為每個線程提供一個獨立的變量副本,使得每個線程都可以獨立地操作自己的變量副本,而不會影響其他線程的變量副本。

在使用DynamicDataSource進(jìn)行數(shù)據(jù)源切換時,每個線程都可以通過ThreadLocal來獨立地設(shè)置和獲取當(dāng)前要使用的數(shù)據(jù)源名稱,避免了多個線程之間數(shù)據(jù)源切換的混亂和不成功的情況。同時,在方法執(zhí)行完畢后,使用ThreadLocal也可以避免內(nèi)存泄漏問題。使用ThreadLocal來存儲當(dāng)前要使用的數(shù)據(jù)源名稱。**setDataSource()**方法用于設(shè)置當(dāng)前要使用的數(shù)據(jù)源名稱,**getDataSource()**方法用于獲取當(dāng)前要使用的數(shù)據(jù)源名稱,**clearDataSource()**方法用于清除當(dāng)前要使用的數(shù)據(jù)源名稱

public class DynamicDataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    /**
     * 設(shè)置當(dāng)前數(shù)據(jù)源的名稱
     */
    public static void setDataSourceName(String dataSourceName) {
        contextHolder.set(dataSourceName);
    }
    /**
     * 獲取當(dāng)前數(shù)據(jù)源的名稱
     */
    public static String getDataSourceName() {
        return contextHolder.get();
    }
    /**
     * 清除當(dāng)前數(shù)據(jù)源的名稱
     */
    public static void clearDataSourceName() {
        contextHolder.remove();
    }
}

3.創(chuàng)建多數(shù)據(jù)源配置

通過yml配置,將多數(shù)據(jù)源獲取到MutilDataSourceProperties

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://****:3306/emp_ts?nullNamePatternMatchesAll=true&tinyInt1isBit=false&useSSL=false&nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
    username: root
    password: root
mutil-datasource:
  connection:
    - dbName: dataSource1
      dbDriver: com.mysql.cj.jdbc.Driver
      dbUrl: jdbc:mysql://****:3306/emp_ts_1?nullNamePatternMatchesAll=true&tinyInt1isBit=false&useSSL=false&nullCatalogMeansCurrent=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
      dbUsername: root
      dbPassword: root
public class DbConnection {
    private String dbName;
    private String dbDialect;
    private String dbDriver;
    private String dbUrl;
    private String dbUsername;
    private String dbPassword;
    public DbConnection() {
    }
    public String getDbName() {
        return this.dbName;
    }
    public String getDbDialect() {
        return this.dbDialect;
    }
    public String getDbDriver() {
        return this.dbDriver;
    }
    public String getDbUrl() {
        return this.dbUrl;
    }
    public String getDbUsername() {
        return this.dbUsername;
    }
    public String getDbPassword() {
        return this.dbPassword;
    }
    public void setDbName(String dbName) {
        this.dbName = dbName;
    }
    public void setDbDialect(String dbDialect) {
        this.dbDialect = dbDialect;
    }
    public void setDbDriver(String dbDriver) {
        this.dbDriver = dbDriver;
    }
    public void setDbUrl(String dbUrl) {
        this.dbUrl = dbUrl;
    }
    public void setDbUsername(String dbUsername) {
        this.dbUsername = dbUsername;
    }
    public void setDbPassword(String dbPassword) {
        this.dbPassword = dbPassword;
    }
}
@Configuration
@ConfigurationProperties(
    prefix = "mutil-datasource"
)
public class MutilDataSourceProperties {
    private List<DbConnection> connection = new ArrayList();
    public MutilDataSourceProperties() {
    }
    public List<DbConnection> getConnection() {
        return this.connection;
    }
    public void setConnection(List<DbConnection> connection) {
        this.connection = connection;
    }
}

4.創(chuàng)建DataSourceConfig

在配置類中創(chuàng)建默認(rèn)數(shù)據(jù)源及獲取其他多數(shù)據(jù)源進(jìn)行創(chuàng)建,默認(rèn)數(shù)據(jù)源為spring.datasource下配置的數(shù)據(jù)源

@Configuration
public class DataSourceConfig {
    @Resource
    private MutilDataSourceProperties mutilDataSourceProperties;
    public DataSourceConfig() {
    }
    @Bean
    @ConfigurationProperties("spring.datasource")
    public DataSource hikariDataSource(DataSourceProperties properties) {
        return DataSourceBuilder.create(properties.getClassLoader()).driverClassName(properties.determineDriverClassName()).url(properties.determineUrl()).username(properties.determineUsername()).password(properties.determinePassword()).build();
    }
    @Bean
    @Primary
    public DynamicDataSource dynamicDataSource(DataSource hikariDataSource) {
        Map<Object, Object> targetDataSources = this.createTargetDataSource();
        return new DynamicDataSource(hikariDataSource, targetDataSources);
    }
     private Map<Object, Object> createTargetDataSource() {
        Map<Object, Object> targetDataSources = new HashMap();
        List<DbConnection> connections = this.mutilDataSourceProperties.getConnection();
        connections.forEach(e -> {
            DataSource dataSource = this.createDataSource(e);
            targetDataSources.put(e.getDbName(), dataSource);
        });
        return targetDataSources;
     }
     public DataSource createDataSource(DbConnection connection) {
        return DataSourceBuilder.create().driverClassName(connection.getDbDriver()).url(connection.getDbUrl())
                .username(connection.getDbName()).password(connection.getDbPassword()).build();
     }
}

5. 使用

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public void addUser(User user) {
        DynamicDataSource.setDataSource("dataSource1");
        userMapper.insert(user);
    }
    @Override
    public void updateUser(User user) {
        DynamicDataSource.setDataSource("dataSource1");
        userMapper.updateById(user);
    }
}

6.優(yōu)缺點

優(yōu)點:

  • 簡單易用:使用 DynamicDataSource 和 ThreadLocal 進(jìn)行動態(tài)數(shù)據(jù)源切換,配置相對簡單,易于上手。
  • 可擴(kuò)展性強(qiáng):通過繼承 AbstractRoutingDataSource 類,可以實現(xiàn)自定義的數(shù)據(jù)源路由策略。并且,由于采用了抽象類,擴(kuò)展性也比較好。
  • 線程安全:使用 ThreadLocal 來存儲當(dāng)前數(shù)據(jù)源的名稱,可以避免多線程之間數(shù)據(jù)源切換的混亂和不成功的情況。

缺點:

  • 不能同時訪問多個數(shù)據(jù)源:在使用 DynamicDataSource 進(jìn)行動態(tài)數(shù)據(jù)源切換時,同一時間只能訪問一個數(shù)據(jù)源,不能同時訪問多個數(shù)據(jù)源。
  • 執(zhí)行效率稍低:在使用 DynamicDataSource 進(jìn)行動態(tài)數(shù)據(jù)源切換時,每次數(shù)據(jù)源切換都需要進(jìn)行一次路由選擇,會稍微影響執(zhí)行效率。
  • 不支持事務(wù)嵌套:在使用 DynamicDataSource 進(jìn)行動態(tài)數(shù)據(jù)源切換時,如果在一個事務(wù)中需要訪問多個數(shù)據(jù)源,那么就需要進(jìn)行事務(wù)管理,而 DynamicDataSource 并不支持事務(wù)嵌套。

綜上所述,使用 DynamicDataSource 和 ThreadLocal 進(jìn)行動態(tài)數(shù)據(jù)源切換,優(yōu)點是簡單易用、可擴(kuò)展性強(qiáng)、線程安全,缺點是不能同時訪問多個數(shù)據(jù)源、執(zhí)行效率稍低、不支持事務(wù)嵌套。在具體使用時需要根據(jù)業(yè)務(wù)場景進(jìn)行選擇。

總結(jié)

到此這篇關(guān)于springboot使用DynamicDataSource動態(tài)切換數(shù)據(jù)源實現(xiàn)的文章就介紹到這了,更多相關(guān)springboot動態(tài)切換數(shù)據(jù)源內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java中調(diào)用GDAL DLL的實現(xiàn)方法

    java中調(diào)用GDAL DLL的實現(xiàn)方法

    本篇文章是對java中調(diào)用GDAL DLL的實現(xiàn)方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • java基于poi導(dǎo)出excel透視表代碼實例

    java基于poi導(dǎo)出excel透視表代碼實例

    這篇文章主要介紹了java基于poi導(dǎo)出excel透視表代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • IntelliJ IDEA 2021.1 推出語音、視頻功能,邊寫代碼邊聊天(功能超級強(qiáng)大)

    IntelliJ IDEA 2021.1 推出語音、視頻功能,邊寫代碼邊聊天(功能超級強(qiáng)大

    這篇文章主要介紹了IntelliJ IDEA 2021.1 推出語音、視頻功能,邊寫代碼邊聊天(功能超級強(qiáng)大),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • IDEA配置tomcat的方法、IDEA配置tomcat運行web項目詳解

    IDEA配置tomcat的方法、IDEA配置tomcat運行web項目詳解

    這篇文章主要介紹了IDEA配置tomcat的方法、IDEA配置tomcat運行web項目詳解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java接口自動化測試框架設(shè)計之Get請求方法和測試詳解

    Java接口自動化測試框架設(shè)計之Get請求方法和測試詳解

    這篇文章主要介紹了Java接口自動化測試框架設(shè)計 Get請求方法和測試,框架設(shè)計我們只是介紹基本的組件,而且框架設(shè)計沒有想象那么難,一步一步跟著做就會了。這篇我們來演示,如果通過Java代碼來實現(xiàn)一個用純代碼實現(xiàn)Http中的Get請求過程,需要的朋友可以參考下
    2019-07-07
  • Java設(shè)計模式之備忘錄模式(Memento模式)介紹

    Java設(shè)計模式之備忘錄模式(Memento模式)介紹

    這篇文章主要介紹了Java設(shè)計模式之備忘錄模式(Memento模式)介紹,memento是一個保存另外一個對象內(nèi)部狀態(tài)拷貝的對象,這樣以后就可以將該對象恢復(fù)到原先保存的狀態(tài),需要的朋友可以參考下
    2015-03-03
  • java中的HashSet與 == 和 equals的區(qū)別示例解析

    java中的HashSet與 == 和 equals的區(qū)別示例解析

    HashSet是Java中基于哈希表實現(xiàn)的集合類,特點包括:元素唯一、無序和可包含null,本文給大家介紹java中的HashSet與 == 和 equals的區(qū)別,感興趣的朋友一起看看吧
    2025-02-02
  • Java SimpleDateFormat線程安全問題原理詳解

    Java SimpleDateFormat線程安全問題原理詳解

    這篇文章主要介紹了Java SimpleDateFormat線程安全問題原理詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • SpringBoot整合Mail輕松實現(xiàn)郵件自動推送功能

    SpringBoot整合Mail輕松實現(xiàn)郵件自動推送功能

    在項目中經(jīng)常會遇到SpringBoot推送消息的業(yè)務(wù),除了站內(nèi)推送通知,郵件推送也是一種常見的方式,本文小編就給大家介紹了SpringBoot整合Mail輕松實現(xiàn)郵件自動推送功能,需要的朋友可以參考下
    2024-12-12
  • Java中實現(xiàn)線程間通信的實例教程

    Java中實現(xiàn)線程間通信的實例教程

    線程通信的目標(biāo)是使線程間能夠互相發(fā)送信號,另一方面線程通信使線程能夠等待其他線程的信號,這篇文章主要給大家介紹了關(guān)于Java中實現(xiàn)線程間通信的相關(guān)資料,本文通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09

最新評論

横山县| 安岳县| 垦利县| 南投县| 霍山县| 松潘县| 临武县| 安阳市| 神木县| 梓潼县| 呼玛县| 东方市| 玉溪市| 措美县| 扬中市| 沿河| 叙永县| 横峰县| 托克托县| 凤庆县| 和平区| 吉林省| 仙桃市| 渭源县| 沁水县| 灵石县| 达拉特旗| 克东县| 凌源市| 漯河市| 中卫市| 四子王旗| 梓潼县| 海安县| 广南县| 乌拉特后旗| 章丘市| 正蓝旗| 五大连池市| 元江| 龙南县|