国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于注解切換、Hikari實(shí)現(xiàn)的SpringBoot動(dòng)態(tài)數(shù)據(jù)源(支持JNDI)

這篇具有很好參考價(jià)值的文章主要介紹了基于注解切換、Hikari實(shí)現(xiàn)的SpringBoot動(dòng)態(tài)數(shù)據(jù)源(支持JNDI)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

實(shí)現(xiàn)效果

先說(shuō)效果,要實(shí)現(xiàn)方法級(jí)別注解切換當(dāng)前數(shù)據(jù)源,不設(shè)置注解時(shí)走默認(rèn)數(shù)據(jù)源,同時(shí)支持JNDI源。

總體思路

Spring框架中存在一個(gè)抽象類(lèi)AbstractRoutingDataSource,他是一個(gè)可以動(dòng)態(tài)選擇當(dāng)前DataSource的路由類(lèi),我們就是要從這里入手,重新實(shí)現(xiàn)數(shù)據(jù)源的切換選擇邏輯。然后借助注解和切面,將當(dāng)前需要的數(shù)據(jù)源名稱(chēng)放在ThreadLocal中,需要時(shí)從當(dāng)前線程取得即可完成數(shù)據(jù)源的切換。
注解部分比較簡(jiǎn)單不再詳說(shuō),看AbstractRoutingDataSource。該類(lèi)文檔寫(xiě)的非常全面,自行翻譯一下就可以看懂。主要看其中的幾個(gè)關(guān)鍵方法。

setTargetDataSources

類(lèi)中存在一個(gè)成員變量targetDataSources,結(jié)合之后的setTargetDataSources方法可知,這里用來(lái)保存目標(biāo)數(shù)據(jù)源。
根據(jù)注釋我們可以知道,targetDataSources的key可以是數(shù)據(jù)源的名字,value是相應(yīng)數(shù)據(jù)源的實(shí)例。
當(dāng)然這里也可是使用其他的保存方式,然后自行改寫(xiě)用來(lái)查找數(shù)據(jù)源的determineCurrentLookupKey方法,默認(rèn)場(chǎng)景就足夠我們使用了。所以我們要構(gòu)建一個(gè)Map出來(lái),其中key用來(lái)區(qū)分?jǐn)?shù)據(jù)源的名字,value放入對(duì)應(yīng)數(shù)據(jù)源的實(shí)例,有幾個(gè)數(shù)據(jù)源就放幾個(gè)進(jìn)去。

	@Nullable
	private Map<Object, Object> targetDataSources;

	/**
	 * Specify the map of target DataSources, with the lookup key as key.
	 * The mapped value can either be a corresponding {@link javax.sql.DataSource}
	 * instance or a data source name String (to be resolved via a
	 * {@link #setDataSourceLookup DataSourceLookup}).
	 * <p>The key can be of arbitrary type; this class implements the
	 * generic lookup process only. The concrete key representation will
	 * be handled by {@link #resolveSpecifiedLookupKey(Object)} and
	 * {@link #determineCurrentLookupKey()}.
	 */
	public void setTargetDataSources(Map<Object, Object> targetDataSources) {
		this.targetDataSources = targetDataSources;
	}

setDefaultTargetDataSource

上面說(shuō)了如何設(shè)置當(dāng)前數(shù)據(jù)源,那如果在開(kāi)發(fā)的時(shí)候每一個(gè)方法都要聲明一下使用哪個(gè)源就太麻煩了,所以Spring提供了一個(gè)方法用來(lái)設(shè)置默認(rèn)的數(shù)據(jù)源,沒(méi)啥可說(shuō)的,傳入DataSource實(shí)例就好了。

	@Nullable
	private Object defaultTargetDataSource;

	/**
	 * Specify the default target DataSource, if any.
	 * <p>The mapped value can either be a corresponding {@link javax.sql.DataSource}
	 * instance or a data source name String (to be resolved via a
	 * {@link #setDataSourceLookup DataSourceLookup}).
	 * <p>This DataSource will be used as target if none of the keyed
	 * {@link #setTargetDataSources targetDataSources} match the
	 * {@link #determineCurrentLookupKey()} current lookup key.
	 */
	public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
		this.defaultTargetDataSource = defaultTargetDataSource;
	}

determineCurrentLookupKey

在設(shè)置好數(shù)據(jù)源之后,接下來(lái)這幾個(gè)尋路方法則是能實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換的重點(diǎn)。afterPropertiesSet方法對(duì)我們以配置的數(shù)據(jù)源進(jìn)行校驗(yàn);如果我們?cè)诘谝徊脚渲脭?shù)據(jù)源map的時(shí)候?qū)ey有特殊處理則要自己實(shí)現(xiàn)抽象方法resolveSpecifiedLookupKey,告訴Spring應(yīng)該怎么解析這個(gè)key值;determineTargetDataSource則最終確定要使用哪一個(gè)數(shù)據(jù)源,其中有一個(gè)方法determineCurrentLookupKey需要關(guān)注,這個(gè)方法會(huì)返回當(dāng)前要使用的數(shù)據(jù)源名字,但他是個(gè)抽象方法,所以我們需要給他重寫(xiě)一下,改為從當(dāng)前線程獲取數(shù)據(jù)源名稱(chēng)。

	@Override
	public void afterPropertiesSet() {
		if (this.targetDataSources == null) {
			throw new IllegalArgumentException("Property 'targetDataSources' is required");
		}
		this.resolvedDataSources = CollectionUtils.newHashMap(this.targetDataSources.size());
		this.targetDataSources.forEach((key, value) -> {
			Object lookupKey = resolveSpecifiedLookupKey(key);
			DataSource dataSource = resolveSpecifiedDataSource(value);
			this.resolvedDataSources.put(lookupKey, dataSource);
		});
		if (this.defaultTargetDataSource != null) {
			this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);
		}
	}

	@Override
	public Connection getConnection(String username, String password) throws SQLException {
		return determineTargetDataSource().getConnection(username, password);
	}

	/**
	 * Retrieve the current target DataSource. Determines the
	 * {@link #determineCurrentLookupKey() current lookup key}, performs
	 * a lookup in the {@link #setTargetDataSources targetDataSources} map,
	 * falls back to the specified
	 * {@link #setDefaultTargetDataSource default target DataSource} if necessary.
	 * @see #determineCurrentLookupKey()
	 */
	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;
	}

	/**
	 * Determine the current lookup key. This will typically be
	 * implemented to check a thread-bound transaction context.
	 * <p>Allows for arbitrary keys. The returned key needs
	 * to match the stored lookup key type, as resolved by the
	 * {@link #resolveSpecifiedLookupKey} method.
	 */
	@Nullable
	protected abstract Object determineCurrentLookupKey();

代碼實(shí)現(xiàn)

思路理順了,代碼寫(xiě)起來(lái)就比較快,直接貼最后代碼,部分地方保留了注釋。

數(shù)據(jù)源切換注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 數(shù)據(jù)源切換注解,默認(rèn)為primary
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TargetDataSource {
    DataSourceEnum value() default DataSourceEnum.PRIMARY;
}

數(shù)據(jù)源切換切面

這里需要特別提醒一下,事務(wù)注解@Transactional默認(rèn)處于切面代理的最后一個(gè),所以我們需要保證數(shù)據(jù)源切換注解優(yōu)先級(jí)要高于事務(wù)注解

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 數(shù)據(jù)源切換切面
 */
@Aspect
@Component
@Order(1)
public class DynamicDataSourceAspect {

    private final static Logger log = LoggerFactory.getLogger(DynamicDataSourceAspect.class);

    @Before(value = "@annotation(targetDataSource)")
    public void beforePointCut(TargetDataSource targetDataSource) {
        log.debug("數(shù)據(jù)源切換為 " + targetDataSource.value().getDataSourceName());
        DynamicDataSourceContextHolder.setDataSource(targetDataSource.value().getDataSourceName());
    }

    @After(value = "@annotation(targetDataSource)")
    public void afterPointCut(TargetDataSource targetDataSource) {
        log.debug("數(shù)據(jù)源恢復(fù)為 " + DataSourceEnum.PRIMARY.getDataSourceName());
        DynamicDataSourceContextHolder.clearDataSource();
    }
}

數(shù)據(jù)源枚舉類(lèi)

/**
 * 數(shù)據(jù)源枚舉類(lèi)
 */
public enum DataSourceEnum {

    PRIMARY("primary"), SECONDARY("secondary");

    private final String dataSourceName;

    public String getDataSourceName() {
        return dataSourceName;
    }

    DataSourceEnum(String dataSourceName) {
        this.dataSourceName = dataSourceName;
    }
}

數(shù)據(jù)源上下文保持類(lèi)

/**
 * 數(shù)據(jù)源上下文線程持有類(lèi)
 */
public class DynamicDataSourceContextHolder {

    /**
     * 存放當(dāng)前線程使用的數(shù)據(jù)源類(lèi)型信息
     */
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();

    public static void setDataSource(String dataSourceType) {
        CONTEXT_HOLDER.set(dataSourceType);
    }

    public static String getDataSource() {
        return CONTEXT_HOLDER.get();
    }

    public static void clearDataSource() {
        CONTEXT_HOLDER.remove();
    }
}

AbstractRoutingDataSource自定義實(shí)現(xiàn)

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.Map;

/**
 * 動(dòng)態(tài)數(shù)據(jù)源切換類(lèi)
 *
 * @author liuenqi
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSource();
    }

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        // 默認(rèn)數(shù)據(jù)源
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        // 所有目標(biāo)數(shù)據(jù)源
        super.setTargetDataSources(targetDataSources);
        // 后處理
        super.afterPropertiesSet();
    }
}

數(shù)據(jù)源注冊(cè)

注意使用jndi源的時(shí)候需要加一個(gè)特定前綴。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-481399.html

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 多數(shù)據(jù)源注冊(cè)類(lèi)
 */
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    private DataSource primaryDataSource;
    private DataSource secondaryDataSource;

    @Override
    public void setEnvironment(Environment environment) {
        initPrimaryDataSource(environment);
        initSecondaryDataSource(environment);
    }

    /**
     * 組裝主數(shù)據(jù)源參數(shù),兼容jdbc-url與jndi
     *
     * @param env Environment
     */
    private void initPrimaryDataSource(Environment env) {
        Map<String, String> paramMap = new HashMap<>(4);
        if (StringUtils.isNotBlank(env.getProperty("spring.datasource.primary.url"))) {
            paramMap.put("url", env.getProperty("spring.datasource.primary.url"));
            paramMap.put("userName", env.getProperty("spring.datasource.primary.username"));
            paramMap.put("password", env.getProperty("spring.datasource.primary.password"));
            paramMap.put("driverClassName", env.getProperty("spring.datasource.primary.driver-class-name"));
        } else {
            paramMap.put("jndi", env.getProperty("spring.datasource.primary.jndi-name"));
        }

        primaryDataSource = buildDataSource(paramMap);
    }

    /**
     * 組裝輔數(shù)據(jù)源參數(shù),兼容jdbc-url與jndi
     *
     * @param env Environment
     */
    private void initSecondaryDataSource(Environment env) {
        if (StringUtils.isNotBlank(env.getProperty("spring.datasource.secondary.url"))) {
            Map<String, String> paramMap = new HashMap<>(4);
            paramMap.put("url", env.getProperty("spring.datasource.secondary.url"));
            paramMap.put("userName", env.getProperty("spring.datasource.secondary.username"));
            paramMap.put("password", env.getProperty("spring.datasource.secondary.password"));
            paramMap.put("driverClassName", env.getProperty("spring.datasource.secondary.driver-class-name"));
            secondaryDataSource = buildDataSource(paramMap);
        } else if (StringUtils.isNotBlank(env.getProperty("spring.datasource.secondary.jndi-name"))) {
            Map<String, String> paramMap = new HashMap<>(2);
            paramMap.put("jndi", env.getProperty("spring.datasource.secondary.jndi-name"));
            secondaryDataSource = buildDataSource(paramMap);
        }
    }

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        Map<Object, Object> targetDataSource = new HashMap<>(2);
        targetDataSource.put("primary", primaryDataSource);
        if (Objects.nonNull(secondaryDataSource)) {
            targetDataSource.put("secondary", secondaryDataSource);
        }

        // 為DynamicDataSource構(gòu)造參數(shù),注意參數(shù)順序
        ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
        constructorArgumentValues.addGenericArgumentValue(primaryDataSource);
        constructorArgumentValues.addGenericArgumentValue(targetDataSource);

        // 構(gòu)造bean放入IOC
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(DynamicDataSource.class);
        beanDefinition.setConstructorArgumentValues(constructorArgumentValues);
        beanDefinition.setSynthetic(true);

        registry.registerBeanDefinition("dataSource", beanDefinition);
    }

    /**
     * 使用HikariDataSource
     *
     * @param paramMap {"url":"JDBC-URL","userName":"數(shù)據(jù)庫(kù)用戶(hù)名","password":"密碼","driverClassName":"驅(qū)動(dòng)名","jndi":"jndi源"}
     * @return HikariDataSource
     */
    private DataSource buildDataSource(Map<String, String> paramMap) {
        HikariConfig hikariConfig = new HikariConfig();
        if (paramMap.containsKey("url")) {
            hikariConfig.setJdbcUrl(paramMap.get("url"));
            hikariConfig.setUsername(paramMap.get("userName"));
            hikariConfig.setPassword(paramMap.get("password"));
            hikariConfig.setDriverClassName(paramMap.get("driverClassName"));
        } else {
            hikariConfig.setDataSourceJNDI("java:comp/env/" + paramMap.get("jndi"));
        }
        return new HikariDataSource(hikariConfig);
    }
}

啟動(dòng)類(lèi)配置

@Import({DynamicDataSourceRegister.class})

application.yml配置

spring:
  datasource:
    primary:
      url: jdbc:mysql://xxxxx
      username: xxxx
      password: xxxxx
      driver-class-name: com.mysql.cj.jdbc.Driver
    secondary: 
      jndi-name: jdbc/db

到了這里,關(guān)于基于注解切換、Hikari實(shí)現(xiàn)的SpringBoot動(dòng)態(tài)數(shù)據(jù)源(支持JNDI)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • springboot實(shí)現(xiàn)多數(shù)據(jù)源配置(Druid/Hikari)

    springboot實(shí)現(xiàn)多數(shù)據(jù)源配置(Druid/Hikari)

    使用springboot+mybatis-plus+(Druid/Hikari)實(shí)現(xiàn)多數(shù)據(jù)源配置 操作步驟: 引入相應(yīng)的maven坐標(biāo) 編寫(xiě)mybatis配置,集成mybatis或mybatis-plus(如果已集成可跳過(guò)) 編寫(xiě)數(shù)據(jù)源配置類(lèi) 編寫(xiě)注解,并通過(guò)aop進(jìn)行增強(qiáng)(編寫(xiě)數(shù)據(jù)源切換代碼) 類(lèi)或方法中使用注解,對(duì)數(shù)據(jù)源進(jìn)行切換 第一步:

    2024年02月13日
    瀏覽(25)
  • [前車(chē)之鑒] SpringBoot原生使用Hikari數(shù)據(jù)連接池升級(jí)到動(dòng)態(tài)多數(shù)據(jù)源的深坑解決方案 & RocketMQ吞掉異常問(wèn)題排查

    [前車(chē)之鑒] SpringBoot原生使用Hikari數(shù)據(jù)連接池升級(jí)到動(dòng)態(tài)多數(shù)據(jù)源的深坑解決方案 & RocketMQ吞掉異常問(wèn)題排查

    當(dāng)前業(yè)務(wù)場(chǎng)景我們使用原生SpringBoot整合Hikari數(shù)據(jù)源連接池提供服務(wù),但是近期業(yè)務(wù)迭代需要使用動(dòng)態(tài)多數(shù)據(jù)源,很自然想到dynamic-source,結(jié)果一系列慘案離奇發(fā)生。。。 原生SpringBoot整合HikariCp數(shù)據(jù)源連接池配置【這個(gè)是沒(méi)問(wèn)題的配置】 而升級(jí)后的動(dòng)態(tài)多數(shù)據(jù)源配置如下:【

    2024年02月01日
    瀏覽(32)
  • SpringBoot動(dòng)態(tài)切換數(shù)據(jù)源

    SpringBoot動(dòng)態(tài)切換數(shù)據(jù)源

    ? Spring提供一個(gè)DataSource實(shí)現(xiàn)類(lèi)用于動(dòng)態(tài)切換數(shù)據(jù)源—— AbstractRoutingDataSource pom.xml 大概的項(xiàng)目結(jié)構(gòu) 注意:這兩個(gè)事務(wù)管理器,并不能處理分布式事務(wù) 鏈接:https://pan.baidu.com/s/1ymxeKYkI-cx7b5nTQX0KWQ? 提取碼:6bii? --來(lái)自百度網(wǎng)盤(pán)超級(jí)會(huì)員V4的分享? ? ? ? ? ? ? ??

    2024年02月06日
    瀏覽(19)
  • SpringBoot——?jiǎng)討B(tài)數(shù)據(jù)源(多數(shù)據(jù)源自動(dòng)切換)

    SpringBoot——?jiǎng)討B(tài)數(shù)據(jù)源(多數(shù)據(jù)源自動(dòng)切換)

    日常的業(yè)務(wù)開(kāi)發(fā)項(xiàng)目中只會(huì)配置一套數(shù)據(jù)源,如果需要獲取其他系統(tǒng)的數(shù)據(jù)往往是通過(guò)調(diào)用接口, 或者是通過(guò)第三方工具比如kettle將數(shù)據(jù)同步到自己的數(shù)據(jù)庫(kù)中進(jìn)行訪問(wèn)。 但是也會(huì)有需要在項(xiàng)目中引用多數(shù)據(jù)源的場(chǎng)景。比如如下場(chǎng)景: 自研數(shù)據(jù)遷移系統(tǒng),至少需要新、老兩

    2024年02月16日
    瀏覽(18)
  • springboot使用DynamicDataSource來(lái)動(dòng)態(tài)切換數(shù)據(jù)源

    DynamicDataSource是一個(gè)數(shù)據(jù)源路由器,可以根據(jù)上下文動(dòng)態(tài)選擇數(shù)據(jù)源??梢栽诿總€(gè)請(qǐng)求或線程中將數(shù)據(jù)源設(shè)置為當(dāng)前需要使用的數(shù)據(jù). 創(chuàng)建一個(gè) DynamicDataSource 類(lèi),它繼承自 AbstractRoutingDataSource 。在該類(lèi)中重寫(xiě)**determineCurrentLookupKey()**方法,該方法返回一個(gè)字符串,用于指示當(dāng)前

    2024年02月05日
    瀏覽(21)
  • SpringBoot從數(shù)據(jù)庫(kù)讀取數(shù)據(jù)數(shù)據(jù)源配置信息,動(dòng)態(tài)切換數(shù)據(jù)源

    SpringBoot從數(shù)據(jù)庫(kù)讀取數(shù)據(jù)數(shù)據(jù)源配置信息,動(dòng)態(tài)切換數(shù)據(jù)源

    ? ? ? ? 首先準(zhǔn)備多個(gè)數(shù)據(jù)庫(kù),主庫(kù)smiling-datasource,其它庫(kù)test1、test2、test3 ? ? ? ? 接下來(lái),我們?cè)谥鲙?kù)smiling-datasource中,創(chuàng)建表databasesource,用于存儲(chǔ)多數(shù)據(jù)源相關(guān)信息。表結(jié)構(gòu)設(shè)計(jì)如下 ? ? ? ? 創(chuàng)建好表之后,向表databasesource中存儲(chǔ)test1、test2、test3三個(gè)數(shù)據(jù)庫(kù)的相關(guān)配置

    2024年01月16日
    瀏覽(37)
  • SpringBoot數(shù)據(jù)源——為什么平時(shí)默認(rèn)線程池是Hikari

    本文主要對(duì)DataSourceAutoConfiguration類(lèi)進(jìn)行講解,然后對(duì)這個(gè)類(lèi)的注解做一個(gè)解釋?zhuān)灾苯哟蜷_(kāi)這個(gè)類(lèi),開(kāi)始看…… ps:我用的版本是2.3.0.RELEASE 目錄 DataSourceAutoConfiguration類(lèi)注解 @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) @ConditionalOnMis

    2024年02月06日
    瀏覽(57)
  • SpringBoot整合多數(shù)據(jù)源,并支持動(dòng)態(tài)新增與切換(詳細(xì)教程)

    SpringBoot整合多數(shù)據(jù)源,并支持動(dòng)態(tài)新增與切換(詳細(xì)教程)

    推薦文章: ????1、springBoot對(duì)接kafka,批量、并發(fā)、異步獲取消息,并動(dòng)態(tài)、批量插入庫(kù)表; ????2、SpringBoot用線程池ThreadPoolTaskExecutor異步處理百萬(wàn)級(jí)數(shù)據(jù); ????3、java后端接口API性能優(yōu)化技巧 ????4、SpringBoot+MyBatis流式查詢(xún),處理大規(guī)模數(shù)據(jù),提高系統(tǒng)的性能和響應(yīng)能力。 一

    2024年02月10日
    瀏覽(25)
  • mybatisplus快速實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源切換

    1.背景 ? 通常一個(gè)系統(tǒng)只需要連接一個(gè)數(shù)據(jù)庫(kù)就可以了。但是在企業(yè)應(yīng)用的開(kāi)發(fā)中往往會(huì)和其他子系統(tǒng)交互,特別是對(duì)于一些數(shù)據(jù)實(shí)時(shí)性要求比較高的數(shù)據(jù),我們就需要做實(shí)時(shí)連接查詢(xún),而不是做同步。這個(gè)時(shí)候就需要用到多數(shù)據(jù)源。 ? 舉個(gè)簡(jiǎn)單的例子某企業(yè)要做訂單網(wǎng)上訂

    2024年02月06日
    瀏覽(25)
  • 一種實(shí)現(xiàn)Spring動(dòng)態(tài)數(shù)據(jù)源切換的方法

    一種實(shí)現(xiàn)Spring動(dòng)態(tài)數(shù)據(jù)源切換的方法

    不在現(xiàn)有查詢(xún)代碼邏輯上做任何改動(dòng),實(shí)現(xiàn)dao維度的數(shù)據(jù)源切換(即表維度) 節(jié)約bdp的集群資源。接入新的寬表時(shí),通常uat驗(yàn)證后就會(huì)停止集群釋放資源,在對(duì)應(yīng)的查詢(xún)服務(wù)器uat環(huán)境時(shí)需要查詢(xún)的是生產(chǎn)庫(kù)的表數(shù)據(jù)(uat庫(kù)表因?yàn)閎dp實(shí)時(shí)任務(wù)停止,沒(méi)有數(shù)據(jù)落入),只進(jìn)行服務(wù)

    2024年02月09日
    瀏覽(20)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包