RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SpringBoot實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源

jf_ro2CN3Fa ? 來(lái)源:稀土掘金技術(shù)社區(qū) ? 2023-12-08 10:53 ? 次閱讀

最近在做業(yè)務(wù)需求時(shí),需要從不同的數(shù)據(jù)庫(kù)中獲取數(shù)據(jù)然后寫(xiě)入到當(dāng)前數(shù)據(jù)庫(kù)中,因此涉及到切換數(shù)據(jù)源問(wèn)題。本來(lái)想著使用Mybatis-plus中提供的動(dòng)態(tài)數(shù)據(jù)源SpringBoot的starter:dynamic-datasource-spring-boot-starter來(lái)實(shí)現(xiàn)。

結(jié)果引入后發(fā)現(xiàn)由于之前項(xiàng)目環(huán)境問(wèn)題導(dǎo)致無(wú)法使用。然后研究了下數(shù)據(jù)源切換代碼,決定自己采用ThreadLocal+AbstractRoutingDataSource來(lái)模擬實(shí)現(xiàn)dynamic-datasource-spring-boot-starter中線程數(shù)據(jù)源切換。

1 簡(jiǎn)介

上述提到了ThreadLocal和AbstractRoutingDataSource,我們來(lái)對(duì)其進(jìn)行簡(jiǎn)單介紹下。

ThreadLocal:想必大家必不會(huì)陌生,全稱:thread local variable。主要是為解決多線程時(shí)由于并發(fā)而產(chǎn)生數(shù)據(jù)不一致問(wèn)題。ThreadLocal為每個(gè)線程提供變量副本,確保每個(gè)線程在某一時(shí)間訪問(wèn)到的不是同一個(gè)對(duì)象,這樣做到了隔離性,增加了內(nèi)存,但大大減少了線程同步時(shí)的性能消耗,減少了線程并發(fā)控制的復(fù)雜程度。

ThreadLocal作用:在一個(gè)線程中共享,不同線程間隔離

ThreadLocal原理:ThreadLocal存入值時(shí),會(huì)獲取當(dāng)前線程實(shí)例作為key,存入當(dāng)前線程對(duì)象中的Map中。

AbstractRoutingDataSource:根據(jù)用戶定義的規(guī)則選擇當(dāng)前的數(shù)據(jù)源,

作用:在執(zhí)行查詢之前,設(shè)置使用的數(shù)據(jù)源,實(shí)現(xiàn)動(dòng)態(tài)路由的數(shù)據(jù)源,在每次數(shù)據(jù)庫(kù)查詢操作前執(zhí)行它的抽象方法determineCurrentLookupKey(),決定使用哪個(gè)數(shù)據(jù)源。

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

程序環(huán)境:

SpringBoot2.4.8

Mybatis-plus3.2.0

Druid1.2.6

lombok1.18.20

commons-lang3 3.10

2.1 實(shí)現(xiàn)ThreadLocal

創(chuàng)建一個(gè)類用于實(shí)現(xiàn)ThreadLocal,主要是通過(guò)get,set,remove方法來(lái)獲取、設(shè)置、刪除當(dāng)前線程對(duì)應(yīng)的數(shù)據(jù)源。

/**
*@author:jiangjs
*@description:
*@date:2023/7/2711:21
**/
publicclassDataSourceContextHolder{
//此類提供線程局部變量。這些變量不同于它們的正常對(duì)應(yīng)關(guān)系是每個(gè)線程訪問(wèn)一個(gè)線程(通過(guò)get、set方法),有自己的獨(dú)立初始化變量的副本。
privatestaticfinalThreadLocalDATASOURCE_HOLDER=newThreadLocal<>();

/**
*設(shè)置數(shù)據(jù)源
*@paramdataSourceName數(shù)據(jù)源名稱
*/
publicstaticvoidsetDataSource(StringdataSourceName){
DATASOURCE_HOLDER.set(dataSourceName);
}

/**
*獲取當(dāng)前線程的數(shù)據(jù)源
*@return數(shù)據(jù)源名稱
*/
publicstaticStringgetDataSource(){
returnDATASOURCE_HOLDER.get();
}

/**
*刪除當(dāng)前數(shù)據(jù)源
*/
publicstaticvoidremoveDataSource(){
DATASOURCE_HOLDER.remove();
}

}

2.2 實(shí)現(xiàn)AbstractRoutingDataSource

定義一個(gè)動(dòng)態(tài)數(shù)據(jù)源類實(shí)現(xiàn)AbstractRoutingDataSource,通過(guò)determineCurrentLookupKey方法與上述實(shí)現(xiàn)的ThreadLocal類中的get方法進(jìn)行關(guān)聯(lián),實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源。

/**
*@author:jiangjs
*@description:實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源,根據(jù)AbstractRoutingDataSource路由到不同數(shù)據(jù)源中
*@date:2023/7/2711:18
**/
publicclassDynamicDataSourceextendsAbstractRoutingDataSource{

publicDynamicDataSource(DataSourcedefaultDataSource,MaptargetDataSources){
super.setDefaultTargetDataSource(defaultDataSource);
super.setTargetDataSources(targetDataSources);
}

@Override
protectedObjectdetermineCurrentLookupKey(){
returnDataSourceContextHolder.getDataSource();
}
}

上述代碼中,還實(shí)現(xiàn)了一個(gè)動(dòng)態(tài)數(shù)據(jù)源類的構(gòu)造方法,主要是為了設(shè)置默認(rèn)數(shù)據(jù)源,以及以Map保存的各種目標(biāo)數(shù)據(jù)源。其中Map的key是設(shè)置的數(shù)據(jù)源名稱,value則是對(duì)應(yīng)的數(shù)據(jù)源(DataSource)。

2.3 配置數(shù)據(jù)庫(kù)

application.yml中配置數(shù)據(jù)庫(kù)信息

#設(shè)置數(shù)據(jù)源
spring:
datasource:
type:com.alibaba.druid.pool.DruidDataSource
druid:
master:
url:jdbc//xxxxxx:3306/test1?characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false
username:root
password:123456
driver-class-name:com.mysql.cj.jdbc.Driver
slave:
url:jdbc//xxxxx:3306/test2?characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false
username:root
password:123456
driver-class-name:com.mysql.cj.jdbc.Driver
initial-size:15
min-idle:15
max-active:200
max-wait:60000
time-between-eviction-runs-millis:60000
min-evictable-idle-time-millis:300000
validation-query:""
test-while-idle:true
test-on-borrow:false
test-on-return:false
pool-prepared-statements:false
connection-properties:false
/**
*@author:jiangjs
*@description:設(shè)置數(shù)據(jù)源
*@date:2023/7/2711:34
**/
@Configuration
publicclassDateSourceConfig{

@Bean
@ConfigurationProperties("spring.datasource.druid.master")
publicDataSourcemasterDataSource(){
returnDruidDataSourceBuilder.create().build();
}

@Bean
@ConfigurationProperties("spring.datasource.druid.slave")
publicDataSourceslaveDataSource(){
returnDruidDataSourceBuilder.create().build();
}

@Bean(name="dynamicDataSource")
@Primary
publicDynamicDataSourcecreateDynamicDataSource(){
MapdataSourceMap=newHashMap<>();
DataSourcedefaultDataSource=masterDataSource();
dataSourceMap.put("master",defaultDataSource);
dataSourceMap.put("slave",slaveDataSource());
returnnewDynamicDataSource(defaultDataSource,dataSourceMap);
}

}

通過(guò)配置類,將配置文件中的配置的數(shù)據(jù)庫(kù)信息轉(zhuǎn)換成datasource,并添加到DynamicDataSource中,同時(shí)通過(guò)@Bean將DynamicDataSource注入Spring中進(jìn)行管理,后期在進(jìn)行動(dòng)態(tài)數(shù)據(jù)源添加時(shí),會(huì)用到。

2.4 測(cè)試

在主從兩個(gè)測(cè)試庫(kù)中,分別添加一張表test_user,里面只有一個(gè)字段user_name。

createtabletest_user(
user_namevarchar(255)notnullcomment'用戶名'
)

在主庫(kù)添加信息:

insertintotest_user(user_name)value('master');

從庫(kù)中添加信息:

insertintotest_user(user_name)value('slave');

我們創(chuàng)建一個(gè)getData的方法,參數(shù)就是需要查詢數(shù)據(jù)的數(shù)據(jù)源名稱。

@GetMapping("/getData.do/{datasourceName}")
publicStringgetMasterData(@PathVariable("datasourceName")StringdatasourceName){
DataSourceContextHolder.setDataSource(datasourceName);
TestUsertestUser=testUserMapper.selectOne(null);
DataSourceContextHolder.removeDataSource();
returntestUser.getUserName();
}

其他的Mapper和實(shí)體類大家自行實(shí)現(xiàn)。

執(zhí)行結(jié)果:

1、傳遞master時(shí):

圖片

2、傳遞slave時(shí):

圖片

通過(guò)執(zhí)行結(jié)果,我們看到傳遞不同的數(shù)據(jù)源名稱,查詢對(duì)應(yīng)的數(shù)據(jù)庫(kù)是不一樣的,返回結(jié)果也不一樣。

在上述代碼中,我們看到DataSourceContextHolder.setDataSource(datasourceName); 來(lái)設(shè)置了當(dāng)前線程需要查詢的數(shù)據(jù)庫(kù),通過(guò)DataSourceContextHolder.removeDataSource(); 來(lái)移除當(dāng)前線程已設(shè)置的數(shù)據(jù)源。使用過(guò)Mybatis-plus動(dòng)態(tài)數(shù)據(jù)源的小伙伴,應(yīng)該還記得我們?cè)谑褂们袚Q數(shù)據(jù)源時(shí)會(huì)使用到DynamicDataSourceContextHolder.push(String ds); 和DynamicDataSourceContextHolder.poll(); 這兩個(gè)方法,翻看源碼我們會(huì)發(fā)現(xiàn)其實(shí)就是在使用ThreadLocal時(shí)使用了棧,這樣的好處就是能使用多數(shù)據(jù)源嵌套,這里就不帶大家實(shí)現(xiàn)了,有興趣的小伙伴可以看看Mybatis-plus中動(dòng)態(tài)數(shù)據(jù)源的源碼。

注:?jiǎn)?dòng)程序時(shí),小伙伴不要忘記將SpringBoot自動(dòng)添加數(shù)據(jù)源進(jìn)行排除哦,否則會(huì)報(bào)循環(huán)依賴問(wèn)題。

@SpringBootApplication(exclude=DataSourceAutoConfiguration.class)

2.5 優(yōu)化調(diào)整

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

在上述中,雖然已經(jīng)實(shí)現(xiàn)了動(dòng)態(tài)切換數(shù)據(jù)源,但是我們會(huì)發(fā)現(xiàn)如果涉及到多個(gè)業(yè)務(wù)進(jìn)行切換數(shù)據(jù)源的話,我們就需要在每一個(gè)實(shí)現(xiàn)類中添加這一段代碼。

說(shuō)到這有小伙伴應(yīng)該就會(huì)想到使用注解來(lái)進(jìn)行優(yōu)化,接下來(lái)我們來(lái)實(shí)現(xiàn)一下。

2.5.1.1 定義注解

我們就用mybatis動(dòng)態(tài)數(shù)據(jù)源切換的注解:DS,代碼如下:

/**
*@author:jiangjs
*@description:
*@date:2023/7/2714:39
**/
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public@interfaceDS{
Stringvalue()default"master";
}

2.5.1.2 實(shí)現(xiàn)aop

@Aspect
@Component
@Slf4j
publicclassDSAspect{

@Pointcut("@annotation(com.jiashn.dynamic_datasource.dynamic.aop.DS)")
publicvoiddynamicDataSource(){}

@Around("dynamicDataSource()")
publicObjectdatasourceAround(ProceedingJoinPointpoint)throwsThrowable{
MethodSignaturesignature=(MethodSignature)point.getSignature();
Methodmethod=signature.getMethod();
DSds=method.getAnnotation(DS.class);
if(Objects.nonNull(ds)){
DataSourceContextHolder.setDataSource(ds.value());
}
try{
returnpoint.proceed();
}finally{
DataSourceContextHolder.removeDataSource();
}
}
}

代碼使用了@Around,通過(guò)ProceedingJoinPoint獲取注解信息,拿到注解傳遞值,然后設(shè)置當(dāng)前線程的數(shù)據(jù)源。對(duì)aop不了解的小伙伴可以自行g(shù)oogle或百度。

2.5.1.3 測(cè)試

添加兩個(gè)測(cè)試方法:

@GetMapping("/getMasterData.do")
publicStringgetMasterData(){
TestUsertestUser=testUserMapper.selectOne(null);
returntestUser.getUserName();
}

@GetMapping("/getSlaveData.do")
@DS("slave")
publicStringgetSlaveData(){
TestUsertestUser=testUserMapper.selectOne(null);
returntestUser.getUserName();
}

由于@DS中設(shè)置的默認(rèn)值是:master,因此在調(diào)用主數(shù)據(jù)源時(shí),可以不用進(jìn)行添加。

執(zhí)行結(jié)果:

1、調(diào)用getMasterData.do方法:

圖片

2、調(diào)用getSlaveData.do方法:

圖片

通過(guò)執(zhí)行結(jié)果,我們通過(guò)@DS也進(jìn)行了數(shù)據(jù)源的切換,實(shí)現(xiàn)了Mybatis-plus動(dòng)態(tài)切換數(shù)據(jù)源中的通過(guò)注解切換數(shù)據(jù)源的方式。

2.5.2 動(dòng)態(tài)添加數(shù)據(jù)源

業(yè)務(wù)場(chǎng)景 :有時(shí)候我們的業(yè)務(wù)會(huì)要求我們從保存有其他數(shù)據(jù)源的數(shù)據(jù)庫(kù)表中添加這些數(shù)據(jù)源,然后再根據(jù)不同的情況切換這些數(shù)據(jù)源。

因此我們需要改造下DynamicDataSource來(lái)實(shí)現(xiàn)動(dòng)態(tài)加載數(shù)據(jù)源。

2.5.2.1 數(shù)據(jù)源實(shí)體

/**
*@author:jiangjs
*@description:數(shù)據(jù)源實(shí)體
*@date:2023/7/2715:55
**/
@Data
@Accessors(chain=true)
publicclassDataSourceEntity{

/**
*數(shù)據(jù)庫(kù)地址
*/
privateStringurl;
/**
*數(shù)據(jù)庫(kù)用戶名
*/
privateStringuserName;
/**
*密碼
*/
privateStringpassWord;
/**
*數(shù)據(jù)庫(kù)驅(qū)動(dòng)
*/
privateStringdriverClassName;
/**
*數(shù)據(jù)庫(kù)key,即保存Map中的key
*/
privateStringkey;
}

實(shí)體中定義數(shù)據(jù)源的一般信息,同時(shí)定義一個(gè)key用于作為DynamicDataSource中Map中的key。

2.5.2.2 修改DynamicDataSource

/**
*@author:jiangjs
*@description:實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源,根據(jù)AbstractRoutingDataSource路由到不同數(shù)據(jù)源中
*@date:2023/7/2711:18
**/
@Slf4j
publicclassDynamicDataSourceextendsAbstractRoutingDataSource{

privatefinalMaptargetDataSourceMap;

publicDynamicDataSource(DataSourcedefaultDataSource,MaptargetDataSources){
super.setDefaultTargetDataSource(defaultDataSource);
super.setTargetDataSources(targetDataSources);
this.targetDataSourceMap=targetDataSources;
}

@Override
protectedObjectdetermineCurrentLookupKey(){
returnDataSourceContextHolder.getDataSource();
}

/**
*添加數(shù)據(jù)源信息
*@paramdataSources數(shù)據(jù)源實(shí)體集合
*@return返回添加結(jié)果
*/
publicvoidcreateDataSource(ListdataSources){
try{
if(CollectionUtils.isNotEmpty(dataSources)){
for(DataSourceEntityds:dataSources){
//校驗(yàn)數(shù)據(jù)庫(kù)是否可以連接
Class.forName(ds.getDriverClassName());
DriverManager.getConnection(ds.getUrl(),ds.getUserName(),ds.getPassWord());
//定義數(shù)據(jù)源
DruidDataSourcedataSource=newDruidDataSource();
BeanUtils.copyProperties(ds,dataSource);
//申請(qǐng)連接時(shí)執(zhí)行validationQuery檢測(cè)連接是否有效,這里建議配置為T(mén)RUE,防止取到的連接不可用
dataSource.setTestOnBorrow(true);
//建議配置為true,不影響性能,并且保證安全性。
//申請(qǐng)連接的時(shí)候檢測(cè),如果空閑時(shí)間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測(cè)連接是否有效。
dataSource.setTestWhileIdle(true);
//用來(lái)檢測(cè)連接是否有效的sql,要求是一個(gè)查詢語(yǔ)句。
dataSource.setValidationQuery("select1");
dataSource.init();
this.targetDataSourceMap.put(ds.getKey(),dataSource);
}
super.setTargetDataSources(this.targetDataSourceMap);
//將TargetDataSources中的連接信息放入resolvedDataSources管理
super.afterPropertiesSet();
returnBoolean.TRUE;
}
}catch(ClassNotFoundException|SQLExceptione){
log.error("---程序報(bào)錯(cuò)---:{}",e.getMessage());
}
returnBoolean.FALSE;
}

/**
*校驗(yàn)數(shù)據(jù)源是否存在
*@paramkey數(shù)據(jù)源保存的key
*@return返回結(jié)果,true:存在,false:不存在
*/
publicbooleanexistsDataSource(Stringkey){
returnObjects.nonNull(this.targetDataSourceMap.get(key));
}
}

在改造后的DynamicDataSource中,我們添加可以一個(gè) private final Map targetDataSourceMap,這個(gè)map會(huì)在添加數(shù)據(jù)源的配置文件時(shí)將創(chuàng)建的Map數(shù)據(jù)源信息通過(guò)DynamicDataSource構(gòu)造方法進(jìn)行初始賦值,即:DateSourceConfig類中的createDynamicDataSource()方法中。

同時(shí)我們?cè)谠擃愔刑砑恿艘粋€(gè)createDataSource方法,進(jìn)行數(shù)據(jù)源的創(chuàng)建,并添加到map中,再通過(guò)super.setTargetDataSources(this.targetDataSourceMap) ;進(jìn)行目標(biāo)數(shù)據(jù)源的重新賦值。

2.5.2.3 動(dòng)態(tài)添加數(shù)據(jù)源

上述代碼已經(jīng)實(shí)現(xiàn)了添加數(shù)據(jù)源的方法,那么我們來(lái)模擬通過(guò)從數(shù)據(jù)庫(kù)表中添加數(shù)據(jù)源,然后我們通過(guò)調(diào)用加載數(shù)據(jù)源的方法將數(shù)據(jù)源添加進(jìn)數(shù)據(jù)源Map中。

在主數(shù)據(jù)庫(kù)中定義一個(gè)數(shù)據(jù)庫(kù)表,用于保存數(shù)據(jù)庫(kù)信息。

createtabletest_db_info(
idintauto_incrementprimarykeynotnullcomment'主鍵Id',
urlvarchar(255)notnullcomment'數(shù)據(jù)庫(kù)URL',
usernamevarchar(255)notnullcomment'用戶名',
passwordvarchar(255)notnullcomment'密碼',
driver_class_namevarchar(255)notnullcomment'數(shù)據(jù)庫(kù)驅(qū)動(dòng)'
namevarchar(255)notnullcomment'數(shù)據(jù)庫(kù)名稱'
)

為了方便,我們將之前的從庫(kù)錄入到數(shù)據(jù)庫(kù)中,修改數(shù)據(jù)庫(kù)名稱。

insertintotest_db_info(url,username,password,driver_class_name,name)
value('jdbc//xxxxx:3306/test2?characterEncoding=utf-8&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useSSL=false',
'root','123456','com.mysql.cj.jdbc.Driver','add_slave')

數(shù)據(jù)庫(kù)表對(duì)應(yīng)的實(shí)體、mapper,小伙伴們自行添加。

啟動(dòng)SpringBoot時(shí)添加數(shù)據(jù)源:

/**
*@author:jiangjs
*@description:
*@date:2023/7/2716:56
**/
@Component
publicclassLoadDataSourceRunnerimplementsCommandLineRunner{
@Resource
privateDynamicDataSourcedynamicDataSource;
@Resource
privateTestDbInfoMappertestDbInfoMapper;
@Override
publicvoidrun(String...args)throwsException{
ListtestDbInfos=testDbInfoMapper.selectList(null);
if(CollectionUtils.isNotEmpty(testDbInfos)){
Listds=newArrayList<>();
for(TestDbInfotestDbInfo:testDbInfos){
DataSourceEntitysourceEntity=newDataSourceEntity();
BeanUtils.copyProperties(testDbInfo,sourceEntity);
sourceEntity.setKey(testDbInfo.getName());
ds.add(sourceEntity);
}
dynamicDataSource.createDataSource(ds);
}
}
}

經(jīng)過(guò)上述SpringBoot啟動(dòng)后,已經(jīng)將數(shù)據(jù)庫(kù)表中的數(shù)據(jù)添加到動(dòng)態(tài)數(shù)據(jù)源中,我們調(diào)用之前的測(cè)試方法,將數(shù)據(jù)源名稱作為參數(shù)傳入看看執(zhí)行結(jié)果。

2.5.2.4 測(cè)試

圖片

通過(guò)測(cè)試我們發(fā)現(xiàn)數(shù)據(jù)庫(kù)表中的數(shù)據(jù)庫(kù)被動(dòng)態(tài)加入了數(shù)據(jù)源中,小伙伴可以愉快地隨意添加數(shù)據(jù)源了。

好了,今天就跟大家嘮叨到這,希望我的叨叨讓大家對(duì)于動(dòng)態(tài)切換數(shù)據(jù)源的方式能夠有更深地理解。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3019

    瀏覽量

    74002
  • 數(shù)據(jù)源
    +關(guān)注

    關(guān)注

    1

    文章

    63

    瀏覽量

    9676
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    173

    瀏覽量

    177

原文標(biāo)題:SpringBoot 實(shí)現(xiàn)動(dòng)態(tài)切換數(shù)據(jù)源,這樣做才更優(yōu)雅!

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    Mybatis 攔截器實(shí)現(xiàn)數(shù)據(jù)源內(nèi)多數(shù)據(jù)庫(kù)切換

    數(shù)據(jù)庫(kù) 現(xiàn)在需要上線報(bào)表服務(wù)來(lái)查詢所有數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行統(tǒng)計(jì),那么現(xiàn)在的問(wèn)題來(lái)了,該如何 滿足在配置一個(gè)數(shù)據(jù)源的情況下來(lái)查詢?cè)?b class='flag-5'>數(shù)據(jù)源下不同
    的頭像 發(fā)表于 12-12 10:23 ?629次閱讀

    LabView動(dòng)態(tài)創(chuàng)建數(shù)據(jù)源的方法

    DSN(Data Source Name,數(shù)據(jù)源名)。LabSQL與數(shù)據(jù)庫(kù)之間的連接就是建立在DSN 基礎(chǔ)之上的。但是這種過(guò)于麻煩,在生成操作程序時(shí)不便于安裝,于是需要一種可以在LabView中直接創(chuàng)建數(shù)據(jù)源的方法。通過(guò)資料查證
    發(fā)表于 09-23 01:53

    【測(cè)試之王LabVIEW】注冊(cè)表應(yīng)用一:動(dòng)態(tài)注冊(cè)數(shù)據(jù)源

    Source Name,數(shù)據(jù)源名)。LabSQL與數(shù)據(jù)庫(kù)之間的連接就是建立在DSN 基礎(chǔ)之上的?,F(xiàn)在通過(guò)修改注冊(cè)表的方式,來(lái)實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建數(shù)據(jù)源
    發(fā)表于 10-31 14:27

    ODBC數(shù)據(jù)源的建立

    我找不到數(shù)據(jù)源這個(gè)選項(xiàng)啊,怎么辦?
    發(fā)表于 04-21 11:39

    如何用現(xiàn)成的軸承數(shù)據(jù)動(dòng)態(tài)數(shù)據(jù)源進(jìn)行動(dòng)態(tài)模擬測(cè)試系統(tǒng)

    如何用現(xiàn)成的軸承數(shù)據(jù)動(dòng)態(tài)數(shù)據(jù)源進(jìn)行動(dòng)態(tài)模擬測(cè)試系統(tǒng)
    發(fā)表于 03-11 15:39

    SpringBoot中的Druid介紹

    SpringBoot中Druid數(shù)據(jù)源配置
    發(fā)表于 05-07 09:21

    SpringBoot項(xiàng)目多數(shù)據(jù)源配置數(shù)據(jù)庫(kù)

    SpringBoot項(xiàng)目多數(shù)據(jù)源配置
    發(fā)表于 06-05 09:51

    數(shù)據(jù)源配置工具

    odbc_for_access.exe1、可直接配置數(shù)據(jù)源。2、可直接創(chuàng)建Access數(shù)據(jù)庫(kù)文件。3、為數(shù)據(jù)庫(kù)配置密碼。
    發(fā)表于 07-01 16:22 ?4次下載

    Delphi教程之動(dòng)態(tài)設(shè)置ODBC數(shù)據(jù)源

    Delphi教程之動(dòng)態(tài)設(shè)置ODBC數(shù)據(jù)源,學(xué)習(xí)Delphi編程的資料。
    發(fā)表于 03-31 11:29 ?13次下載

    基于LDA主題模型進(jìn)行數(shù)據(jù)源選擇方法

    聯(lián)邦搜索是從大規(guī)模深層網(wǎng)上獲取信息的一種重要技術(shù)。給定一個(gè)用戶查詢,聯(lián)邦搜索系統(tǒng)需要解決的一個(gè)主要問(wèn)題是數(shù)據(jù)源選擇問(wèn)題,即從海量數(shù)據(jù)源中選出一組最有可能返回相關(guān)結(jié)果的數(shù)據(jù)源。現(xiàn)有的數(shù)據(jù)源
    發(fā)表于 01-04 15:00 ?0次下載
    基于LDA主題模型進(jìn)行<b class='flag-5'>數(shù)據(jù)源</b>選擇方法

    Deep Web數(shù)據(jù)源選擇和集成方法

    針對(duì)基于數(shù)據(jù)源質(zhì)量選擇方法的數(shù)據(jù)源數(shù)據(jù)爬取時(shí)存在代價(jià)大、重復(fù)率高的問(wèn)題,提出一種結(jié)合兩層選擇模型的Deep Web數(shù)據(jù)源選擇和集成方法。該方法根據(jù)
    發(fā)表于 02-09 15:24 ?0次下載
    Deep Web<b class='flag-5'>數(shù)據(jù)源</b>選擇和集成方法

    數(shù)據(jù)倉(cāng)庫(kù)入門(mén)之創(chuàng)建數(shù)據(jù)源

    首先需要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù)源,SSAS(分析服務(wù))將利用數(shù)據(jù)源來(lái)連接數(shù)據(jù)庫(kù)。一、準(zhǔn)備環(huán)境二、啟動(dòng)SSDT,新建項(xiàng)目三、創(chuàng)建數(shù)據(jù)源
    發(fā)表于 02-24 14:48 ?2532次閱讀
    <b class='flag-5'>數(shù)據(jù)</b>倉(cāng)庫(kù)入門(mén)之創(chuàng)建<b class='flag-5'>數(shù)據(jù)源</b>

    SpringBoot分布式事務(wù)的解決方案(JTA+Atomic+多數(shù)據(jù)源

    首先,到底啥是分布式事務(wù)呢,比如我們?cè)趫?zhí)行一個(gè)業(yè)務(wù)邏輯的時(shí)候有兩步分別操作A數(shù)據(jù)源和B數(shù)據(jù)源,當(dāng)我們?cè)贏數(shù)據(jù)源執(zhí)行數(shù)據(jù)更改后,在B數(shù)據(jù)源執(zhí)行
    的頭像 發(fā)表于 04-11 11:05 ?1627次閱讀

    SpringBoot數(shù)據(jù)源及事務(wù)解決方案

    當(dāng)Spring容器創(chuàng)建AbstractRoutingDataSource對(duì)象時(shí),通過(guò)調(diào)用afterPropertiesSet復(fù)制上述目標(biāo)數(shù)據(jù)源。由此可見(jiàn),一旦數(shù)據(jù)源實(shí)例對(duì)象創(chuàng)建完畢,業(yè)務(wù)無(wú)法再添加新的數(shù)據(jù)源
    的頭像 發(fā)表于 04-12 11:22 ?2213次閱讀

    weblogic修改數(shù)據(jù)源需要重啟嗎

    WebLogic是一款支持Java EE(Java Enterprise Edition)規(guī)范的應(yīng)用服務(wù)器,通過(guò)WebLogic可進(jìn)行數(shù)據(jù)源的配置和管理。在WebLogic中修改數(shù)據(jù)源是否需要重啟
    的頭像 發(fā)表于 12-05 16:09 ?1392次閱讀
    RM新时代网站-首页