欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

基于 Spring 和 iBATIS 的動態(tài)可更新多數(shù)據(jù)源持

系統(tǒng) 1810 0

前言

我們時常會遇到一些 web 項目,需要從不同的數(shù)據(jù)源中抓取數(shù)據(jù)來進行分析,而這些數(shù)據(jù)源是有可能變化的,需要用戶來進行動態(tài)的維護和添加??墒?,大多數(shù)的 web 程序使用了應用服務器或者容器中間件來管理數(shù)據(jù)源的生命周期,因此數(shù)據(jù)源的變化自然不能夠獨立于程序,而需要由專業(yè)人士去進行維護,必要時還需要重新發(fā)布程序來適應數(shù)據(jù)源的變化,而且數(shù)據(jù)源的個數(shù)、數(shù)據(jù)庫的類型也都會有所限制。

那么怎樣才可以突破以上這些局限,徹底實現(xiàn)由用戶遠程對數(shù)據(jù)源進行維護和管理的需求呢?本文提出了一個有效的解決方案,該方案的大體思路如下:將數(shù)據(jù)源的配置信息保存在一個地址相對固定的數(shù)據(jù)庫或本地文件系統(tǒng)中,系統(tǒng)將依據(jù)這些配置信息自動生成數(shù)據(jù)源(每當數(shù)據(jù)信息發(fā)生變化時,系統(tǒng)將重新生成新數(shù)據(jù)源),然后通過工廠模式的持久層將這些數(shù)據(jù)源自動分配給對應的類對象使用。如此,只需要一個用戶界面,來對此數(shù)據(jù)源的配置信息進行管理,就可以實現(xiàn)由用戶自主維護數(shù)據(jù)源系統(tǒng)的目的了。下文將以一個 Spring+iBATIS 框架的實例,來詳細描述該解決方案的實現(xiàn)。

?

相關(guān)技術(shù)介紹

iBATIS

Apache iBATIS 是 Clinton Begin 開發(fā),現(xiàn)在由 Apache 基金會支持的用于加快 JDBC 編程的經(jīng)過泛化的框架,是當前 IT 項目中使用很廣泛的一個半自動 ORM 框架,區(qū)別于 Hibernate 之類的全自動框架,iBATIS 對數(shù)據(jù)庫的操作擁有更加靈活的控制,對于那些經(jīng)常需要調(diào)用本地數(shù)據(jù)庫函數(shù)自定義 SQL 語句,或是喜歡自己優(yōu)化 SQL 執(zhí)行效率的開發(fā)者來說,iBATIS 是一個非常不錯的選擇。而得到廣泛應用的開源企業(yè)架構(gòu) Spring Framework,也很好的將 iBATIS 進行了集成,使得 iBATIS 在 Spring 中的使用更加便利、快捷。下面是 iBATIS 的一些關(guān)鍵組件:

  • SqlMapClient :是 iBATIS 的重要接口,是線程安全的。這個接口涉及到對 SQL 映射的執(zhí)行和批處理。
  • Sqlmap - config.xml :是使用 iBATIS 的起點,負責把所有的 SQL 映射文件(sqlmap.xml)組合在一起。該配置文件可以告訴 iBATIS 如何連接數(shù)據(jù)庫,以及獲取哪些 SQL 映射文件(sqlmap.xml)。
  • sqlmap.xml 包含了我們將要運行的 SQL 語句,被 Sqlmap-config.xml 文件所引用。

基于 Spring 和 iBATIS 的動態(tài)可更新多數(shù)據(jù)源持久層
圖 1.iBATIS 架構(gòu)圖
?

我們之所以選用 iBATIS 而不是 Hibernate 來作為本解決方案的開發(fā)框架,主要是因為相比 Hibernate 來說 iBATIS 更具靈活性,可以更為方便地對其結(jié)構(gòu)進行改寫。尤其是在對不同數(shù)據(jù)庫結(jié)構(gòu)的封裝方面,iBATIS 更適用于對實現(xiàn)相同邏輯的不同數(shù)據(jù)庫結(jié)構(gòu)的支持。反觀 Hibernate 則需要對數(shù)據(jù)庫結(jié)構(gòu)進行封裝,這就意味著對不同的數(shù)據(jù)庫結(jié)構(gòu)要生成不同的 PO 類,這會使開發(fā)工作變得繁瑣。當然用戶也可以選擇使用 Hibernate 來作為框架,其理念是相同的,不同的只是實現(xiàn)手段。

Spring 對 iBATIS 的支持

Spring 通過 DAO 模式,提供了對 iBATIS 的良好支持。

  • SqlMapClient :是 iBATIS 中的主要接口,通過 xml 配置文件可以讓 Spring 容器來管理 SqlMapClient 對象的創(chuàng)建,Spring 提供了 SqlMapClientFactoryBean 來生成該對象。
  • SqlMapClientFactoryBean :SqlMapClientFactoryBean 是由 Spring 所提供的,用來生成 SqlMapClient 對象的一個工廠類。當使用 Spring 配置文件將 SqlMapClientFactoryBean 作為一個 SqlMapClient 的實現(xiàn)類進行注入時,Spring 容器將根據(jù)接口里的定義來調(diào)用其 getObject 方法,最終返回一個 SqlMapClient 接口的實現(xiàn)類。SqlMapClientFactoryBean 生成的對象擁有兩個重要屬性,configLocation 屬性用來確定 sqlmap-config.xml,dataSource 屬性用來確定數(shù)據(jù)源。
  • SqlMapClientDaoSupport :Spring 提供的數(shù)據(jù)庫操作類,應用程序的持久層 DAO 則可以繼承這個類。SqlMapClientDaoSupport 需要 Spring 為其注入 SqlMapClient 接口的實現(xiàn)對象,來確定使用何種數(shù)據(jù)源和使用何種 sqlmap-config.xml。
?

持久層的架構(gòu)和設(shè)計

如上節(jié)所述可知,如果要使傳統(tǒng)的 Spring+iBATIS 框架支持動態(tài)的多數(shù)據(jù)源持久層,則需要對其進行改良。而數(shù)據(jù)源是由 SqlMapClient 對象的屬性所定義的,所以要想辦法通過變更 SqlMapClient 接口的實現(xiàn)對象來達到目的。Spring 是使用 XML 配置文件來存儲 SqlMapClient 對象的信息,因此只需要能夠根據(jù)數(shù)據(jù)源配置信息來動態(tài)生成該 XML 配置文件,來實現(xiàn)對 SqlMapClient 接口的動態(tài)注入即可。

?

?

?

?

持久層架構(gòu)的具體處理流程如上圖所示:

1.創(chuàng)建配置文件生成類 SqlMapClientFactory,當應用服務器啟動時,Spring 框架將啟動 SqlMapClientFactory 類的 init 方法(每當數(shù)據(jù)源配置信息發(fā)生變化時也重新啟動此方法),該方法將讀取數(shù)據(jù)庫或本地文件系統(tǒng)中存儲的數(shù)據(jù)源配置信息,然后動態(tài)的生成 Spring XML 配置文件。在此 XML 配置文件中,根據(jù)不同的數(shù)據(jù)源定義了很多不同的 SqlMapClient 對象,并定義了其相對應的數(shù)據(jù)源和 sqlmap-config 文件。

2.創(chuàng)建 SqlMapClient 接口的實現(xiàn)類 RoutingSqlMapClient,并通過 Spring 將生成的所有 SqlMapClient 對象以 Map 的結(jié)構(gòu)形式注入到 RoutingSqlMapClient 中,當其被調(diào)用時將根據(jù)要求使用相應的 SqlMapClient 實現(xiàn)對象來對 RoutingSqlMapClient 的方法進行重寫。

3.將 RoutingSqlMapClient 注入到所有繼承了 SqlMapClientDaoSupport 的 DAO 實現(xiàn)類中,DAO 將根據(jù)實際需求決定使用哪個數(shù)據(jù)源。

?

持久層的具體實現(xiàn)

使用 SqlMapClientFactory 類生成 XML 配置文件

如上文的描述,第一步應該創(chuàng)建 SqlMapClientFactory 類,并創(chuàng)建一個用來生成 SqlMapClient 的 XML 配置文件的方法。然后配置 Spring,使其能在程序啟動時自動調(diào)用 SqlMapClient 的該方法。該方法要從本地文件系統(tǒng)或地址相對固定的數(shù)據(jù)庫系統(tǒng)中讀取數(shù)據(jù)源配置信息,SqlMapClientFactory 所讀取的數(shù)據(jù)源配置信息的主要字段如下:

注:<hostname> 是數(shù)據(jù)庫所在的服務器地址,<portNum> 是數(shù)據(jù)庫所用服務端口號,<databaseName> 是數(shù)據(jù)庫名稱,<userName> 是數(shù)據(jù)庫用戶名,<password> 是該用戶的密碼


表 1 數(shù)據(jù)源配置信息

ID Name Connection User Password DBType
00001 PROJECTA jdbc:db2:// <hostname> : <portNum> / <databaseName> <userName> <password> DB2
00002 PROJECTB jdbc:microsoft:sqlserver:// <hostname> :
<portNum>
;DatabaseName= <databaseName>
<userName> <password> sqlserver
00003 PROJECTC jdbc:db2:// <hostname> : <portNum> / <databaseName> <userName> <password> DB2
00004 PROJECTD jdbc:db2:// <hostname> : <portNum> / <databaseName> <userName> <password> DB2

?

SqlMapClientFactory 將根據(jù)這些配置信息生成相應的 SqlMapClient 對象的 XML 配置文件。下面詳細介紹一下該 XML 配置文件的主要構(gòu)成。

1,根據(jù)數(shù)據(jù)源配置信息的 ID 和 Name,生成所有 SqlMapClient 接口實現(xiàn)對象的 Map 列表。


清單 1. routingSqlMapClient 配置

              				 
 <bean id="routingSqlMapClient" class="com.ibm.mbps.tsd.dao.RoutingSqlMapClient"> 
  <property name="targetSqlMapClients"> 
 <map key-type="java.lang.String"> 
 <entry key="PROJECTA" value-ref="sqlmapClient_00001"/> 
 <entry key="PROJECTB" value-ref="sqlmapClient_00002"/> 
 <entry key="PROJECTC" value-ref="sqlmapClient_00003"/> 
 <entry key="PROJECTD" value-ref="sqlmapClient_00004"/> 
		……
    </map> 
 </property> 
 </bean> 

            

?

2,為每個 SqlMapClient 接口實現(xiàn)對象創(chuàng)建數(shù)據(jù)源,數(shù)據(jù)源根據(jù)上文的配置信息生成。


清單 2. data source 配置示例

              				 
 <bean id="datasource_00001" class="org.apache.commons.dbcp.BasicDataSource"> 
 <property name="driverClassName"> 
    <value>com.ibm.db2.jcc.DB2Driver</value> 
  </property> 
  <property name="url"> 
    <value> jdbc:db2://hostname:portNum/databaseName</value> 
  </property> 
  <property name="username"> 
    <Value>userName</value> 
  </property> 
  <property name="password"> 
    <value>password</value> 
 </property> 
 </bean> 

            

?

3,為每個 SqlMapClient 對象注入數(shù)據(jù)源和 sqlmap-config 配置文件,應該注意的是該 sqlmap-config 配置文件是針對某一類數(shù)據(jù)源的,比如多個數(shù)據(jù)源的數(shù)據(jù)庫類型和數(shù)據(jù)庫內(nèi)容都相同,那么就應該使用同一張配置文件。


清單 3. SqlMapClient 對象配置示例

              				 
 <bean id=" sqlmapClient_00001" class="org.springframework.orm.ibatis.SqlMapClient 
 FactoryBean"> 
 <property name="configLocation" value="classpath:/sqlmap/db2/sql-map-config.xml"/> 
    <property name="dataSource"> 
      <ref local=" datasource_00001"/> 
    </property> 
 </bean> 

            

?

重寫 SqlMapClient 接口的實現(xiàn)類 RoutingSqlMapClient

生成了 SqlMapClient 對象后,我們還要創(chuàng)建一個 RoutingSqlMapClient 的實現(xiàn)類用來重寫相應的 SqlMapClient 接口方法。RoutingSqlMapClient 將創(chuàng)建一個 Map 變量去承接上文生成的 SqlMapClient 實現(xiàn)對象的 Map 列表,然后根據(jù)關(guān)鍵字來判斷用哪個實現(xiàn)對象來動態(tài)的重寫 RoutingSqlMapClient 類。RoutingSqlMapClient 使用變量 targetSqlMapClients 來接收 SqlMapClient 對象列表。


清單 4. RoutingSqlMapClient 類的代碼片段

              				 
 public class RoutingSqlMapClient implements SqlMapClient { 
 private Map<String, SqlMapClient> targetSqlMapClients; 
 public void flushDataCache() 
 { 
 targetSqlMapClients.get(getDSType()).flushDataCache(); 
 } 
 public SqlMapSession getSession() 
 { 
 return targetSqlMapClients.get(getDSType()).getSession(); 
 } 
 public int delete(String id, Object parameterObject) throws SQLException 
 { 
 return targetSqlMapClients.get(getDSType()).delete(id,parameterObject); 
 } 
 public Object insert(String id, Object parameterObject) throws SQLException 
 { 
 return targetSqlMapClients.get(getDSType()).insert(id,parameterObject); 
 } 
 public List queryForList(String id, Object parameterObject) throws SQLException { 
 return targetSqlMapClients.get(getDSType()).queryForList(id,parameterObject); 
 } 
……
 } 

            

?

創(chuàng)建繼承 SqlMapClientDaoSupport 的 DAO 類

我們選擇使用 RoutingSqlMapClient 重寫 SqlMapClient 的實現(xiàn)方法,而不是將 SqlMapClient 實現(xiàn)對象直接注入到對應 DAO 中的原因是:一個 DAO 類有可能對應多個數(shù)據(jù)源,如果將只包含一個數(shù)據(jù)源的 SqlMapClient 實現(xiàn)對象直接注入 DAO,那將嚴重限制 DAO 的可重用性。因此我們將整個 SqlMapClient 實現(xiàn)對象的列表裝載入 RoutingSqlMapClient 類,在邏輯層定義使用哪一個 SqlMapClient 對象對 RoutingSqlMapClient 進行重寫,持久層的 DAO 架構(gòu)如下圖所示:


圖 3. 持久層 DAO 架構(gòu)圖( 查看大圖
基于 Spring 和 iBATIS 的動態(tài)可更新多數(shù)據(jù)源持久層 ?

DAO 實體類繼承 SqlMapClientDaoSupport 并實現(xiàn)相應不同的接口。如圖所示,不同的接口對應不同的上層邏輯,而實現(xiàn)其邏輯的 DAO 實現(xiàn)類引用了不同的數(shù)據(jù)源和 sqlmap-config.xml,這些數(shù)據(jù)源和 XML 定義在 SqlMapClient 對象內(nèi),當我們調(diào)用持久層 DAO 類對數(shù)據(jù)庫進行操作時需要先調(diào)用 RoutingSqlMapClient 內(nèi)的 setDSType() 方法來確定使用哪個數(shù)據(jù)源,并使用對應的 SqlMapClient 實現(xiàn)對象對 RoutingSqlMapClient 進行重寫,這樣就可以把對應此數(shù)據(jù)源的 SqlMapClient 以 RoutingSqlMapClient 對象的形式傳入到 DAO 內(nèi),實現(xiàn)多數(shù)據(jù)源并存的結(jié)構(gòu)了。

支持動態(tài)更新的多數(shù)據(jù)源持久層開發(fā)完畢后,還應該為用戶開發(fā)一套 UI 組件來使用戶能夠?qū)?shù)據(jù)源信息進行更新和維護。而每次用戶更新完畢都要調(diào)用 SqlMapClientFactory 類的 init 方法,來重新生成 SqlMapClient 的 XML 配置文件,這樣就可以不重新啟動服務器而實現(xiàn)數(shù)據(jù)源的動態(tài)更新和添加了。

?

總結(jié)

本文描述了,可動態(tài)更新的多數(shù)據(jù)源持久層系統(tǒng)的一種實現(xiàn)方式,對于開發(fā)類似項目的開發(fā)者有一定的借鑒作用。但是由于本文的主要目的是闡述一種理念方法而不是具體實現(xiàn),所以一些相關(guān)技術(shù)及具體實現(xiàn)沒有寫出,但開發(fā)者可以根據(jù)本文的思路選用自己喜歡的方式來進行實現(xiàn),此外對于一些名詞和 iBATIS 及 Spring 的功能沒有予以詳細介紹,建議對 iBATIS 架構(gòu)不熟的讀者能夠自行參考其它教程。本文選用 Spring+iBATIS 框架僅作為示例,但僅僅是建議使用,不對使用結(jié)果和效果做任何保證。(本文內(nèi)容僅代表作者個人觀點)

基于 Spring 和 iBATIS 的動態(tài)可更新多數(shù)據(jù)源持久層


更多文章、技術(shù)交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 久久99中文字幕 | 欧美激情久久久久久久久 | 欧美精品一二区 | 啪啪小视频网站 | 日韩欧美视频一区二区三区 | 国产精品拍自在线观看 | 国产在线视频色综合 | 欧美在线观看一区 | 男女激情免费视频 | 亚洲精品乱码8久久久久久日本 | 欧美成人一级 | 国产精品嫩草影视在线观看 | 啊哈不要啊 | 极品xxxx欧美一区二区 | 亚洲精品视频一区二区三区 | 日本高清视频www夜色资源网 | 九九99久久精品在免费线bt | 亚洲一区二区欧美日韩 | 特黄aaaaa日本大片免费看 | 色综合久久综精品 | 欧美一级二级三级 | 欧美电影网站在线观看影片 | 久久免费国产视频 | 国产美女福利视频福利 | 三级特黄视频 | 亚洲网站免费看 | 久久夜色精品国产亚洲噜噜 | 久草久草视频 | 丰满年轻岳中文字幕一区二区 | 亚洲精品无码成人A片在线虐 | a级片免费视频 | 亚洲精品黄色 | 好吊色欧美一区二区三区四区 | 一级做一级爱a做片性视频视频 | 免费黄色大全 | 国产精品久久久久久久午夜 | 不卡中文一二三区 | 一级片九九 | 亚洲激情一区 | 九九这里只有精品视频 | 一级做a爰片久久毛片看看 欧美日韩精品国产一区二区 |