❶ 如何在spring框架中解決多數據源的問題
在 我們的項目中遇到這樣一個問題:我們的項目需要連接多個資料庫,而且不同的客戶在每次訪問中根據需要會去訪問不同的資料庫。我們以往 在 spring 和 hibernate 框架中總是配置一個數據源,因而 sessionFactory 的dataSource 屬性總是指向這個 數據源並且恆定不變,所有 DAO 在使用 sessionFactory 的時候都是通過這個數據源訪問資料庫。但是現在,由於項目的需要,我們 的 DAO 在訪問 sessionFactory 的時候都不得不在多個數據源中不斷切換,問題就出現了:如何讓 sessionFactory 在執 行數據持久化的時候,根據客戶的需求能夠動態切換不同的數據源?我們能不能在 spring 的框架下通過少量修改得到解決?是否有什麼設計模式可以利用 呢?
問題的分析
我 首先想到在 spring 的 applicationContext 中配置所有的 dataSource 。這些 dataSource 可能是各種 不同類型的,比如不同的資料庫: Oracle 、 SQL Server 、 MySQL 等,也可能是不同的數據源:比如 apache 提供的 org.apache.commons.dbcp.BasicDataSource 、 spring 提供的 org.springframework.jndi.JndiObjectFactoryBean 等。然後 sessionFactory 根據客戶的 每次請求,將dataSource 屬性設置成不同的數據源,以到達切換數據源的目的。
但 是,我很快發現一個問題:當多用戶同時並發訪問資料庫的時候會出現資源爭用的問題。這都是「單例模式」惹的禍。眾所周知,我們在使用 spring 框架 的時候,在 beanFactory 中注冊的 bean 基本上都是採用單例模式,即 spring 在啟動的時候,這些 bean 就裝載到內存中, 並且每個 bean 在整個項目中只存在一個對象。正因為只存在一個對象,對象的所有屬性,更准確說是實例變數,表現得就如同是個靜態變數(實際上「靜 態」與「單例」往往是非常相似的兩個東西,我們常常用「靜態」來實現「單例」)。拿我們的問題來說, sessionFactory 在整個項目中只有一 個對象,它的實例變數 dataSource 也就只有一個,就如同一個靜態變數一般。如果不同的用戶都不斷地去修改 dataSource 的值,必然 會出現多用戶爭用一個變數的問題,對系統產生隱患。
通過以上的分析,解決多數據源訪問問題的關鍵,就集中在 sessionFactory 在執行數據持久化的時候,能夠通過某段代碼去根據客戶的需要動態切換數據源,並解決資源爭用的問題。
問題的解決
(一) 採用 Decorator 設計模式
要 解決這個問題,我的思路鎖定在了這個 dataSource 上了。如果 sessionFactory 指向的 dataSource 可以根據客戶的 需求去連接客戶所需要的真正的數據源,即提供動態切換數據源的功能,那麼問題就解決了。那麼我們怎麼做呢?去修改那些我們要使用 的 dataSource 源碼嗎?這顯然不是一個好的方案,我們希望我們的修改與原dataSource 代碼是分離的。根據以上的分析,使 用 GoF 設計模式中的 Decorator 模式(裝飾者模式)應當是我們可以選擇的最佳方案。
什 么是「 Decorator 模式」?簡單點兒說就是當我們需要修改原有的功能,但我們又不願直接去修改原有的代碼時,設計一個 Decorator 套 在原有代碼外面。當我們使用 Decorator 的時候與原類完全一樣,當 Decorator 的某些功能卻已經修改為了我們需要修改的功 能。 Decorator 模式的結構如圖。
我 們本來需要修改圖中所有具體的 Component 類的一些功能,但卻並不是去直接修改它們的代碼,而是在它們的外面增加一 個 Decorator 。 Decorator 與具體的 Component 類都是繼承的 AbstractComponent ,因此它長得和具 體的 Component 類一樣,也就是說我們在使用 Decorator 的時候就如同在使用 ConcreteComponentA 或者 ConcreteComponentB 一樣,甚至那些使用 ConcreteComponentA 或者 ConcreteComponentB 的客 戶程序都不知道它們用的類已經改為了 Decorator ,但是 Decorator 已經對具體的 Component 類的部分方法進行了修改,執 行這些方法的結果已經不同了。
(二) 設計 MultiDataSource 類
現 在回到我們的問題,我們需要對 dataSource 的功能進行變更,但又不希望修改 dataSource 中的任何代碼。我這里指 的 dataSource 是所有實現 javax.sql.DataSource 介面的類,我們常用的包括 apache 提供的 org.apache.commons.dbcp.BasicDataSource 、 spring 提供的 org.springframework.jndi.JndiObjectFactoryBean 等,這些類我們不可能修改它們本身,更不可能對它們一 個個地修改以實現動態分配數據源的功能,同時,我們又希望使用 dataSource 的 sessionFactory 根本就感覺不到這樣的變 化。 Decorator 模式就正是解決這個問題的設計模式。
首先寫一個 Decorator 類,我取名叫 MultiDataSource,通過它來動態切換數據源 。同時在配置文件中將sessionFactory的dataSource屬性由原來的某個具體的dataSource改為MultiDataSource。如圖:
對 比原Decorator 模式, AbstractComponent 是一個抽象類,但在這里我們可以將這個抽象類用介面來代替,即 DataSource 介面,而 ConcreteComponent 就是那些 DataSource 的實現類, 如 BasicDataSource 、JndiObjectFactoryBean 等。 MultiDataSource 封裝了具體的 dataSource,並實現了數據源動態切換:
java 代碼
public class MultiDataSource implements DataSource {
private DataSource dataSource = null ;
public MultiDataSource(DataSource dataSource){
this .dataSource = dataSource;
}
public Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
//其它DataSource介面應當實現的方法
public DataSource getDataSource(){
return this .dataSource;
}
}
public void setDataSource(DataSource dataSource) {
this .dataSource = dataSource;
}
}
客 戶在發出請求的時候,將dataSourceName放到request中,然後把request中的數據源名通過調用 newMultiDataSource(dataSource) 時可以告訴 MultiDataSource 客戶需要的數據源,就可以實現動態切換數 據源了。但細心的朋友會發現這在單例的情況下就是問題的,因為 MultiDataSource 在系統中只有一個對象,它的實例變 量 dataSource 也只有一個,就如同一個靜態變數一般。正因為如此, 單例模式讓許多設計模式都不得不需要更改,這將在我的《「單例」更改了我 們的設計模式》中詳細討論。那麼,我們在單例模式下如何設計呢?
(三) 單例模式下的 MultiDataSource
在 單例模式下,由於我們在每次調用 MultiDataSource 的方法的時候, dataSource 都可能是不同的,所以我們不能 將 dataSource 放在實例變數 dataSource 中,最簡單的方式就是在方法 getDataSource() 中增加參數,告 訴 MultiDataSource 我到底調用的是哪個 dataSource :
java 代碼
public DataSource getDataSource(String dataSourceName){
log.debug( "dataSourceName:" +dataSourceName);
try {
if (dataSourceName== null ||dataSourceName.equals( "" )){
return this .dataSource;
}
return (DataSource) this .applicationContext.getBean(dataSourceName);
} catch (NoSuchBeanDefinitionException ex){
throw new DaoException( "There is not the dataSource
}
}
值得一提的是,我需要的數據源已經都在spring 的配置文件中注冊, dataSourceName 就是其對應的 id 。
xml 代碼
< bean id = "dataSource1"
class = "org.apache.commons.dbcp.BasicDataSource" >
< property name = "driverClassName" >
< value > oracle.jdbc.driver.OracleDriver value >
property >
......
bean >
< bean id = "dataSource2"
class = "org.apache.commons.dbcp.BasicDataSource" >
< property name = "driverClassName" >
< value > oracle.jdbc.driver.OracleDriver value >
property >
......
bean >
為了得到spring 的 ApplicationContext , MultiDataSource 類必須實現介面org.springframework.context.ApplicationContextAware ,並且實現方法:
java 代碼
private ApplicationContext applicationContext = null ;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this .applicationContext = applicationContext;
}
如此這樣,我就可以通過this . applicationContext .getBean(dataSourceName) 得到 dataSource 了。
(四) 通過線程傳遞 dataSourceName
查 看以上設計, MultiDataSource 依然無法運行,因為用戶在發出請求時,他需要連接什麼資料庫,其數據源名是放在 request 中的, 要將 request 中的數據源名傳給 MultiDataSource ,需要經過 BUS 和 DAO ,也就是說為了把數據源名傳 給 MultiDataSource , BUS 和 DAO 的所有方法都要增加 dataSourceName 的參數,這是我們不願看到的。寫一個 類,通過線程的方式跳過 BUS 和 DAO 直接傳遞給 MultiDataSource 是一個不錯的設計:
java 代碼
public class SpObserver {
private static ThreadLocal local = new ThreadLocal();
public static void putSp(String sp) {
local.set(sp);
}
public static String getSp() {
return (String)local.get();
}
}
做一個filter ,每次客戶發出請求的時候就調用 SpObserver.petSp ( dataSourceName ) ,將 request 中的dataSourceName 傳遞給 SpObserver 對象。 最後修改 MultiDataSource 的方法 getDataSource() :
java 代碼
public DataSource getDataSource(){
String sp = SpObserver.getSp();
return getDataSource(sp);
}
完整的MultiDataSource 代碼在附件中。
(五) 動態添加數據源
通 過以上方案,我們解決了動態分配數據源的問題,但你可能提出疑問:方案中的數據源都是配置在 spring 的 ApplicationContext 中,如果我在程序運行過程中動態添加數據源怎麼辦?這確實是一個問題,而且在我們的項目中也確實遇 到。 spring 的 ApplicationContext 是在項目啟動的時候載入的。載入以後,我們如何動態地載入新的 bean 到 ApplicationContext 中呢?我想到如果用 spring 自己的方法解決這個問題就好了。所幸的是,在查看 spring 的源代碼後,我找到了這樣的代碼,編寫了 DynamicLoadBean 類,只要 調用loadBean() 方法,就可以將某個或某 幾個配置文件中的 bean 載入到 ApplicationContext 中(見附件)。不通過配置文件直接載入對象,在spring 的源碼中也 有,感興趣的朋友可以自己研究。
(六) 在 spring 中配置
在完成了所有這些設計以後,我最後再嘮叨一句。我們應當在 spring 中做如下配置:
xml 代碼
< bean id = "dynamicLoadBean" class = "com.htxx.service..DynamicLoadBean" > bean >
< bean id = "dataSource" class = "com.htxx.service..MultiDataSource" >
< property name = "dataSource" >
< ref bean = "dataSource1" />
property >
bean >
< bean id = "sessionFactory" class = "org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name = "dataSource" >
< ref bean = "dataSource" />
property >
......
bean >
其中dataSource 屬性實際上更准確地說應當是 defaultDataSource ,即 spring 啟動時以及在客戶沒有指定數據源時應當指定的默認數據源。
該方案的優勢
以上方案與其它方案相比,它有哪些優勢呢?
首 先,這個方案完全是在 spring 的框架下解決的,數據源依然配置在 spring 的配置文件中, sessionFactory依然去配置它 的 dataSource 屬性,它甚至都不知道 dataSource 的改變。唯一不同的是在真正的 dataSource 與 sessionFactory 之間增加了一個 MultiDataSource 。
其 次,實現簡單,易於維護。這個方案雖然我說了這么多東西,其實都是分析,真正需要我們寫的代碼就只有 MultiDataSource 、 SpObserver 兩個類。 MultiDataSource 類真正要寫的只 有 getDataSource() 和getDataSource(sp) 兩個方法,而 SpObserver 類更簡單了。實現越簡單,出錯的可能 就越小,維護性就越高。
最 後,這個方案可以使單數據源與多數據源兼容。這個方案完全不影響 BUS 和 DAO 的編寫。如果我們的項目在開始之初是單數據源的情況下開發,隨著項 目的進行,需要變更為多數據源,則只需要修改 spring 配置,並少量修改 MVC 層以便在請求中寫入需要的數據源名,變更就完成了。如果我們的項 目希望改回單數據源,則只需要簡單修改配置文件。這樣,為我們的項目將增加更多的彈性。
特 別說明:實例中的DynamicLoadBean在web環境下運行會出錯,需要將類中AbstractApplicationContext改為 org.springframework.context.。
❷ C# FastReport 設置多個數據源
沒有做FastReport
但是想法是:如果可以自由的選擇需要的數據源的話,是不是可以傳遞參數,根據參數不同,來設置不同的數據源呢.
❸ 為什麼kettle可以接入多種數據源
kettle可以接入多種數據源原因:由於kettle是純java編輯,所以kettle連接mysql庫的時候需要mysql的java連接包,網路下載一個mysql的java連接驅動。
kettle使用文件資源庫不需要用戶名和密碼,如果沒有資源庫可以點擊右上角的"+"新建資源庫。為建立資料庫的資源庫,本例選擇使用文件資源庫,選擇確定後會要求選擇文件資源庫的路徑,並給文件資源庫設置一個ID和名稱。
kettle無代碼拖拽式構建數據管道:
kettle可Pentaho採用拖拽組件、連線、配置的方式來構建數據管道,透過超過200個不同的組件,用戶可以在不編寫一句代碼就能輕松完成對數據源讀取。
對數據進行關聯、過濾、格式轉換、計算、統計、建模、挖掘、輸出到不同的數據目標。極大程度地降低開發技術門檻和有效減低開發和維護成本。
❹ 為什麼要設置數據源 怎樣設置Access數據源
設置數據源,就相當於打電話撥號一樣,只有撥通了才能通話,這也一樣,建立數據源實現了網站中IIS對資料庫的訪問連接。具體方法如下:
1、在控制面板中,雙擊管理工具,然後打開ODBC數據源管理器。
2、在「系統DSN」選項卡中,單擊「添加」按鈕,打開「創建新數據源」對話框,在「名稱」列表框中選擇「Driver
do
Microsoft
Access(*.mdb)」點擊『完成』。
3、在出現的
odbc
microsoft
access
安裝中,填寫『數據源名』(隨便起個名),單擊『選擇』按鈕選擇你的資料庫文件(進行連接),沒有的話點擊旁邊的『創建』。操作完成後單擊『確定』。
4、odbc操作基本完成了,剩下的操作就是設置你要進行操作的軟體了。
❺ Spring動態配置多數據源的簡介
Spring配置多數據源的方式和具體使用過程。
Spring對於多數據源,以資料庫表為參照,大體上可以分成兩大類情況:
一是,表級上的跨資料庫。即,對於不同的資料庫卻有相同的表(表名和表結構完全相同)。
二是,非表級上的跨資料庫。即,多個數據源不存在相同的表。
Spring2.x的版本中採用Proxy模式,就是我們在方案中實現一個虛擬的數據源,並且用它來封裝數據源選擇邏輯,這樣就可以有效地將數據源選擇邏輯從Client中分離出來。Client提供選擇所需的上下文(因為這是Client所知道的),由虛擬的DataSource根據Client提供的上下文來實現數據源的選擇。 具體的實現就是,虛擬的DataSource僅需繼承AbstractRoutingDataSource實現determineCurrentLookupKey()在其中封裝數據源的選擇邏輯。
一、動態配置多數據源
1. 數據源的名稱常量類:
package com.frogking.datasource;
public class DataSourceConst {
public static final String Admin=Admin;
public static final String User = User;
}
2. 建立一個獲得和設置上下文環境的類,主要負責改變上下文數據源的名稱: package com.frogking.datasource;
public class DataSourceContextHolder {
private static final ThreadLocal contextHolder =
new ThreadLocal(); // 線程本地環境
// 設置數據源類型
public static void setDataSourceType(String dataSourceType) {
contextHolder.set(dataSourceType);
}
// 獲取數據源類型
public static String getDataSourceType() {
return (String) contextHolder.get();
}
// 清除數據源類型
public static void clearDataSourceType () {
contextHolder.remove();
}
}
3. 建立動態數據源類,注意,這個類必須繼承AbstractRoutingDataSource,且實現方法determineCurrentLookupKey,該方法返回一個Object,一般是返回字元串: package com.frogking.datasource;
publicclass DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
// 在進行DAO操作前,通過上下文環境變數,獲得數據源的類型
return DataSourceContextHolder. getDataSourceType();
}
}
4. 編寫spring的配置文件配置多個數據源
<!-- 數據源相同的內容 -->
<bean class=org.springframework.jdbc.datasource.DriverManagerDataSource id=parentDataSource>
<property name=driverClassName>
<value>com.mysql.jdbc.Driver</value>
</property>
<property name=username>
<value>root</value>
</property>
<property name=password>
<value>1234</value>
</property>
</bean>
<!-- 以下配置各個數據源的特性 -->
<!-- 資料庫test -->
<bean parent=parentDataSource id=adminDataSource>
<property name=url>
<value>jdbc:mysql://localhost:3306/test</value>
</property>
</bean>
<!-- 不同的資料庫test2 -->
<bean parent=parentDataSource id=userDataSource>
<property name=url>
<value>jdbc:mysql://localhost:3306/test2</value>
</property>
</bean>
<!-- end 配置各個數據源的特性 -->
5. 編寫spring配置文件配置多數據源映射關系
<bean class=com.frogking.datasource.DynamicDataSource id=dataSource>
<property name=targetDataSources>
<map key-type=java.lang.String>
<entry value-ref= adminDataSource key=Admin></entry>
<entry value-ref= userDataSource key=User></entry>
</map>
</property>
<property name=defaultTargetDataSource ref=adminDataSource >
</property>
</bean>
在這個配置中第一個property屬性配置目標數據源,<map key-type=java.lang.String>中的key-type必須要和靜態鍵值對照類DataSourceConst中的值的類型相 同;<entry key=User value-ref=userDataSource/>中key的值必須要和靜態鍵值對照類中的值相同,如果有多個值,可以配置多個< entry>標簽。第二個property屬性配置默認的數據源。
6. 配置hibernate,和普通的hibernate、spring結合的配置一樣:
<!-- sessionFactory的配置 -->
<BEAN class=org.springframework.orm.hibernate3.LocalSessionFactoryBean id=sessionFactory>
<property name=dataSource>
<REF local=dataSource> </REF>
</property>
<!-- 實體類資源映射 -->
<property name=mappingResources>
<LIST>
<VALUE>com/frogking/entity/User.hbm.xml </VALUE>
<VALUE>com/frogking/entity/Admin.hbm.xml</VALUE> </LIST>
</property>
<!-- 為sessionFactory 配置Hibernate屬性 -->
<property name=hibernateProperties>
<PROPS>
<PROP key=hibernate.dialect> org.hibernate.dialect.MySQLDialect
</PROP>
<PROP key=hibernate.show_sql>true</PROP> <PROP key=hibernate.connection.autocommit>false</PROP> <PROP key=hibernate.cache.use_query_cache>false</PROP> <PROP key=hibernate.max_fetch_depth>2</PROP> <PROP key=hibernate.bytecode.use_reflection_optimizer>true</PROP>
</PROPS>
</property>
</BEAN>
<!-- 為配置sessionFactory -->
<BEAN class=com.frogking..LoginHibernateDao id=loginDao>
<property name=sessionFactory>
<REF local=sessionFactory> </REF>
</property>
</BEAN>
❻ 什麼是多數據源
有兩個DB,一個叫DB1,一個叫DB2,在項目中兩個DB都用到了。就這樣/
❼ 資料庫編程 為什麼要設置數據源
在VC中動態載入ODBC的方法
在使用 VC、 VB、 Delphi等高級語言編寫資料庫應用程序時,往往需要用戶自己在控制面板中配置 ODBC數據源。對於一般用戶而言,配置 ODBC數據源可能是一件比較困難的工作。而且,在實際應用中,用戶往往要求在同一個應用程序中訪問不同的數據源,因此採用一般的載入方法就有了無法克服的缺陷。為能在程序中完成這一工作,方便應用程序的使用,本文以 VC為開發環境介紹兩種在應用程序中動態載入 ODBC系統數據源的方法。
方法一:修改注冊表
設計思路
一般情況下,當用戶在控制面板中配置好 ODBC數據源後, Windows系統便在注冊表中加入了一些子鍵來存儲用戶的配置結果。當應用程序需要用到數據源時, Windows便會通知底層介面查閱注冊表中該數據源的配置。如果用戶刪除了某個 ODBC數據源,那麼也會在注冊表中有所反應。如果配置的數據源是用戶數據源, Windows系統便會修改注冊表的 HKEY_CURRENT_USER\SOFTWARE\ODBC\ODBC.INI子鍵;如果配置的數據源是系統數據源, Windows系統便會修改注冊表的 HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI主鍵。因此,我們可以在應用程序中使用 Windows API中的注冊表編輯函數來完成 Windows所做的工作,這樣就可以達到動態載入數據源的目的。
具體實現
對於不同類型的數據源,注冊表的修改也各有不同,但基本上都要修改兩個地方。一個是在 ODBC.INI子鍵下建立一個與數據源描述名同名的子鍵,並在該子鍵下建立與數據源配置相關的項;另一個是在 \ODBC.INI\ODBC Data Sources子鍵下建立一個新項以便告訴驅動程序管理器 ODBC數據源的類型。下面以配置一個 Microsoft Access數據源為例給出實現此功能的函數的代碼。
/* strSourceName是要創建的數據源名, strSourceDb是資料庫存放路徑, strDescription是數據源的描述字元串。* /
BOOL CLoadOdbcDlg:: LoadDbSource(CString strSourceName,CString strSourceDb, CString strDescription)
{
//存放打開的注冊表鍵
HKEY hKey;
DWORD dw;
//存放注冊表 API函數執行的返回值
LONG lReturn;
//存放要打開的子鍵
CString strSubKey;
//檢測是否安裝了 MS Access ODBC driver:odbcjt32.dll
//獲得 Windows系統目錄
char sysDir[MAX_PATH];
char drvName[]=" \\odbcjt32.dll" ;
::GetSystemDirectory (sysDir,MAX_PATH);
strcat(sysDir,drvName);
CFileFind findFile;
if(!findFile.FindFile (sysDir))
{
AfxMessageBox("您的計算機系統中沒有安裝 MS Access的 ODBC驅動程序 odbcjt32.dll,您將無法載入該類數據源。 " ,MB_OK|MB_ICONSTOP);
return false;
}
strSubKey=" SOFTWARE\\ODBC\\ODBC.INI\\"+ strSourceName;
//創建 ODBC數據源在注冊表中的子鍵
lReturn=::RegCreateKeyEx(HKEY_LOCAL_
MACHINE,(LPCTSTR)strSubKey,0,NULL,REG_OPTION
_NON_VOLATILE,KEY_WRITE,NULL,& hKey,& dw);
if(lReturn != ERROR_SUCCESS)
return false;
//設置數據源的各項參數
CString strDbq=strSourceDb;
CString strDriver=sysDir;
DWORD dwDriverId=25;
CString strFil=" MS Access" ;
CString strPwd=strSourceName;
DWORD dwSafeTransactions=0;
CString strUid=strSourceName;
::RegSetValueEx (hKey," DBQ" ,0L,REG_SZ,
(CONST BYTE* )((LPCTSTR) strDbq),strDbq .GetLength ()) ; ::RegSetValueEx (hKey," Description" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strDescription),strDescription.GetLength());
::RegSetValueEx (hKey," Driver" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strDriver),strDriver .GetLength ());
::RegSetValueEx (hKey," DriverId" ,0L,REG_DWORD,(CONST BYTE* )(& dwDriverId),sizeof(dw));
::RegSetValueEx (hKey," FIL" ,0L,REG_SZ,
(CONST BYTE* )((LPCTSTR) strFil),strFil .GetLength ());
::RegSetValueEx (hKey," PWD" ,0L,REG_SZ,
(CONST BYTE* )((LPCTSTR)strPwd),strPwd.GetLength ()) ; ::RegSetValueEx (hKey," SafeTransactions" ,0L,
REG_DWORD,(CONST BYTE* )(& dwSafeTransactions),sizeof(dw));
::RegSetValueEx (hKey," UID" ,0L,REG_SZ,
(CONST BYTE* )((LPCTSTR)strUid),strUid .GetLength ()); ::RegCloseKey(hKey);
//創建 ODBC數據源的 Jet子鍵
strSubKey+ =" \\Engines\\Jet" ;
lReturn=::RegCreateKeyEx (HKEY_LOCAL_MACHINE ,(LPCTSTR)strSubKey,0,NULL,REG_OPTION_NON_
VOLATILE,KEY_WRITE,NULL,& hKey,& dw);
if(lReturn != ERROR_SUCCESS)
return false;
//設置該子鍵下的各項參數
CString strImplict=" " ;
CString strUserCommit=" Yes" ;
DWORD dwPageTimeout=5;
DWORD dwThreads=3;
DWORD dwMaxBufferSize=2048;
::RegSetValueEx (hKey," ImplictCommitSync" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strImplict),strImplict.GetLength ()+ 1);
::RegSetValueEx (hKey," MaxBufferSize" ,0L,REG_DWORD,(CONST BYTE* )(& dwMaxBufferSize),sizeof(dw));
::RegSetValueEx (hKey," PageTimeout" ,0L,REG_DWORD,(CONST BYTE* )(& dwPageTimeout),sizeof(dw));
::RegSetValueEx (hKey," Threads" ,0L,REG_DWORD,(CONST BYTE* )(& dwThreads),sizeof(dw));
::RegSetValueEx (hKey," UserCommitSync" ,0L,REG_SZ,(CONST BYTE* )((LPCTSTR)strUserCommit),strUserCommit.GetLength ());
::RegCloseKey (hKey);
//設置 ODBC資料庫引擎名稱
lReturn=::RegOpenKeyEx (HKEY_LOCAL_MACHINE, " SOFTWARE\\ODBC\\ODBC.INI\\ODBC Data Sources" ,0L,KEY_WRITE,& hKey);
if(lReturn !=ERROR_SUCCESS)
return false;
CString strDbType=" Microsoft Access Driver (* .mdb)" ; ::RegSetValueEx (hKey,strSourceName,0L,REG_SZ,(CONST BYTE* )((LCTSTR)strDbType),strDbType.GetLength ());
return true;
}
由於在動態載入中,一般只會改變資料庫文件、數據源說明以及數據源描述,故上述函數可以實現應用中的大部分要求。如果應用中還需要作更多的改變,那麼也可以通過改變函數參數的方式加以實現。對於需要動態載入多種類型數據源的情況,可以用具有不同參數的重載函數去實現。
方法二:利用 DLL
設計思路
Windows系統子目錄中的動態鏈接庫 Odbcinst.dll提供了一個可以動態地增加、修改和刪除數據源的函數 SQLConfigDataSource()。該函數的原型如下:
BOOL SQLConfigDataSource(HWND hwndParent,WORD fRequest, LPCSTR lpszDriver, LPCSTR lpszAttributes);
hwndParent參數是父窗口句柄。如果該值為 NULL,將不會顯示與父窗口有關的對話框。
fRequest參數可以設置為下面的數值之一:
� ODBC_ADD_DSN:增加一個新的用戶數據源;
� ODBC_CONFIG_DSN:修改(配置)一個已經存在的用戶數據源;
� ODBC_REMOVE_DSN:刪除一個已經存在的用戶數據源;
� ODBC_ADD_SYS_DSN:增加一個新的系統數據源;
� ODBC_CONFIG_SYS_DSN:修改 (配置 )一個已經存在的系統數據源;
� ODBC_REMOVE_SYS_DSN:刪除一個已經存在的系統數據源。
lpszDriver參數用於傳遞資料庫引擎的名字,等同於方法一中 strDbType變數。
lpszAttirbutes參數是關鍵字的值,即一連串的 " keyname=value"字元串,每兩個字元串之間用 " \"隔開,如 DSN=Personnel Data\0UID=Smith\0DATABASE=Personnel。關於該參數的詳細設置請參閱 MSDN中 SQLConfigDataSource()函數的幫助文檔和各種 ODBC驅動程序文檔。
具體實現
由於 VC的預設庫文件中不包含 SQLConfigDataSource()函數,因此使用該函數之前需要將 odbcinst.h文件包含在工程的頭文件中,在工程的 Settings屬性對話框 Link屬性頁的 Object/library moles編輯框中增加 odbc32.lib,同時保證系統目錄 system32下有文件 odbccp32.dll。
仍以 Microsoft Access為例,設置數據源名為 demo,數據源描述為 "示例數據源 ",那麼在需要動態載入數據源的地方加入下列代碼即可:
::SQLConfigDataSource (NULL,ODBC_ADD_SYS_DSN," Microsoft Access Driver (* .mdb)"," DSN=demo\0Descirption=示例資料庫 " );
小結
上述兩種方法都可以實現動態載入各種類型的 ODBC數據源,並且在 Windows95/98/NT/2000環境下調試通過。方法一在實現時需要較多的代碼,方法二所需代碼雖少,但需要額外文件的支持,而且隨著數據源配置的靈活性的增加,為了形成 lpszAttributes字元串,其代碼長度也會相應增加。由於從控制面板配置數據源使得程序員可以獲得更加直觀的理解,所以對於注冊表中各項值以及相應項名稱的獲得除了可以查閱相關驅動程序的文檔外,程序員也可以在編程前先通過控制面板配置 ODBC數據源,然後根據注冊表中相應部分的內容進行編程。
======================================
Create Access data source name dynamically
This article was contributed by Madhava V.
This sample in this article was created using VC 5.0. The necessary .h and .lib files are present in the zip.
To create a DSN at run time you could use the SQLConfigDataSource API. Internally this information is stored in the registry. The syntax is attached below
SQLConfigDataSource(NULL,ODBC_ADD_DSN,"Microsoft Access Driver (*.mdb)\0","DSN=TestDB\0DBQ=D:\\Database\\Friends.mdb\0DEFAULTDIR=D:\\DATABASE\0\0");
The problem is that if you want to accept the values from the user or set these values at run time by passing CString or char* will not work. This is because, when sprintf encounters a /0 it assumes it is the end of the string and ignores the rest of the data.
As a workaround you have to use the below mentioned code.
The following code places : where a /0 is expected and there is a loop which replaces a ":" with "/0". You will not be in a position to use sprintf because, when it encounters a /0 it assumes it is the end of the string and ignores the rest of the data.
char* szDesc;
int mlen;
szDesc=new char[256];
sprintf(szDesc,"DSN=%s: DESCRIPTION=TOC support source: DBQ=%s: FIL=MicrosoftAccess: DEFAULTDIR=D:\\Database:: ","TestDB","D:\\Friends.mdb");
mlen = strlen(szDesc);
for (int i=0; i <mlen; i++)
{
if (szDesc[i] == ':')
szDesc[i] = '\0';
}
if (FALSE == SQLConfigDataSource(NULL,ODBC_ADD_DSN,"Microsoft Access Driver (*.mdb)\0",(LPCSTR)szDesc))
MessageBox(hwnd,"Failed","INFORMATION",MB_OK);
else
MessageBox(hwnd,"Sucess","INFORMATION",MB_OK);
❽ 怎麼做Websphere6中配置多個數據源
方法/步驟
1
登錄was控制台,選擇「資源」->"JDBC提供程序"->選擇"應用伺服器"->"新建"
2
選擇「資料庫類型」->選擇「提供程序類型」->選擇」實施類型「
3
輸入」資料庫類路徑信息「,/home/jar是指存放驅動程序jar的目錄,後面不要加上jar包的名稱。,後續操作直接「下一步」-「完成」。
4
選擇」JDBC-數據源「->"新建"
5
」輸入基本數據源信息「,選擇」創建新建J2C認證別名「
選擇」新建「
輸入相關信息,別名可以任意輸入,「用戶標識」和「密碼」是指連接資料庫用的用戶名和密碼。
一定要選擇「保存」,設置才能生效。
輸入基本數據源信息,JNDI名稱要記住,在配置應用里資料庫連接的時候會用到它。
創建數據源,選擇」Oracle驅動程序「
URL中每個冒號前後不能有空格,URL中的IP地址是資料庫伺服器的IP, 緊跟著IP的是埠號,oracle默認的是1521,之後是SID,oracle默認是orcl。
直接單擊」完成「
一定要選擇「保存」,設置才能生效。
選擇剛剛新建的數據源,單擊」測試鏈接「
測試通過說明配置正確,否則配置錯誤。
❾ SpringCloud項目,每個微服務配置一個數據源好還是微服務里配置多個數據源好
我們這邊是所有服務統一使用同一數據源,資料庫連接信息配置到環境變數之中,所有微服務統一讀取這組環境變數。
你要是設置成多數據源,未來系統故障時查找數據方面的問題多麻煩啊。
對於業務需要,真的是有比如兩個數據源的,假設是主數據源A和輔數據源B,那麼可以基於輔數據源B搭建一個微服務,暴露API,由主數據源服務在需要時調用輔數據源的服務的API就好。
不過如果輔數據源可能只有一個最簡單的查詢,沒有更多操作了,你在主數據源服務中直接配置多數據源也沒問題。
我仔細想了一下,似乎還是各個數據源單獨起一個自己的服務這樣更有「分布式微服務」的樣子呢。