數據訪問中間件及其在物流倉儲支撐平臺中的應用
作者:鮑鵬
                        來源:通信市場網
                        日期:2011-01-07 09:26:19
                    
                        摘要:本文分析現有的數據庫訪問中間件的現狀,在物流倉儲綜合支撐平臺中應用輕量級的ORM框架,介紹數據訪問中間件的使用,通過具體實例表明,使用數據訪問中間件可以簡化數據存取訪問過程,使擴展性得到了大大的增強,并可以最大限度的不影響上層的應用程序的結構,減少系統維護的難度。
                    
                    
                      引言
 
傳統的數據庫訪問技術對于數據庫操作的復雜性,以及擴展性差等問題已漸漸制約分布式應用集成的需要,利用新技術,研究和開發新的數據庫訪問中間件成為數據庫研究領域的主要方向之一。中間件技術將傳統的客戶機/服務器體系結構擴展為三層體系結構模式,即客戶機-中間件-服務器體系模式。
 
本文所述系統為物流倉儲綜合支撐平臺,用于支撐多種基本物流業務,包括報關(單證)、存儲、運輸、訂艙等基本業務類型以及由這些基本業務類型所組成的各種復合業務類型。系統采用表示層、業務處理層與數據存儲層三層結構的CS架構,表示層的主要職責是為用戶提供信息以及提供交互。表示層細分為界面外觀層與界面邏輯層。業務邏輯層的主要職責是對用戶提交的輸入指令與數據做校驗,再加工后將數據提交到數據存儲層或將數據存儲層的數據提取后返回給表示層。數據存儲層主要職責是存儲用戶數據。其中數據訪問層與事務處理層,使用Castle ActiveRecord框架作為數據庫持久層,框架提供對數據訪問層與事務處理層的封裝。
 
數據訪問中間件定義
 
中間件為可以為其他程序員服用、實現特定功能接口的程序包或服務。中間件在操作系統軟件,網絡和數據庫之上,應用軟件之下,總的作用是為處于上層的應用程序提供開發環境,幫助用戶高效、靈活的開發和集成更加復雜的應用軟件。IDC對中間件的定義為:中間件是一種獨立的系統軟件或服務程序,分布式應用軟件借助這種軟件在不同的技術之間共享資源,中間件定位于客戶機服務器的操作系統之上,管理計算機資源和網絡通信。按照IDC的分類方法,中間件可分為六類:終端仿真、數據訪問中間件、遠程過程調用中間件、消息中間件、交易中間件、對象中間件。
 
本文涉及的數據訪問中間件為中間件的一種,是指一切連接應用程序和數據庫的軟件,位于客戶機服務器的操作系統之上,通過使用統一接口提供對運行在多種平臺上的不同數據庫的訪問。通過使用數據訪問中間件,可擴展性得到了大大的增強,可以最大限度的不影響上層的應用程序的結構,減少系統維護的難度。由于對于數據庫的操作都被封裝在數據庫訪問中間件,用戶對數據的管理實現了對數據庫操作的透明性。
 
本文所述系統使用的數據庫訪問中間件為Castle .Net 中的額ActiveRecord組件,它是一個輕量級的ORM組件,它在底層封裝了NHibernate. NHibernate是一個基于.Net,用于關系數據庫的對象持久化類庫,它是著名的Hibernate的.Net版本,采用xml配置文件進行關系的映射。在ActiveRecord中,則對這種方式進行了進一步的封裝,采用特性(Attribute)的方式進行映射。
 
數據訪問中間件實現
 
本系統采用表示層、業務處理層與數據存儲層三層結構的CS架構。如下圖所示為該系統項目軟件結構如圖一所示。
 
由于本項目采用C/S架構,故僅主要使用Castle中的數據訪問ORM框架Castle ActiveRecord。Castle ActiveRecord是Castle中提供的一個輕量級數據訪問框架,它在底層封裝了NHibernate的操作,使用特性來代替映射文件,從而提供非常簡潔的O/R映射(一對一、一對多,多對多關系等均可以表達)。同時,它還實現了對象的最基本的CRUD操作,這在很大程度上減少了開發的工作量。另外,ActiveRecord支持HQL(Hibernate Query Language ),使開發人員可以自定義一些復雜查詢。其他特性:多數據庫連接、支持事務處理、維護方便性。提供對數據訪問層與事務處理層的封裝。
 
數據訪問中間件的配置
 
ActiveRecord在底層封裝了NHibernate,在框架啟動時需要指定相關的配置信息。可以使用自己的XML文件來保存配置信息,例如有一個AppConfig.xml的文件。
<activerecord>
<config>
<add
key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
<add
key="hibernate.dialect" value="NHibernate.Dialect.MsSql2005Dialect" />
<add key="hibernate.connection.provider"value="NHibernate.Connection.DriverConnectionProvider" />
<add
key="hibernate.connection.connection_string" value="Data Source=.\SQLEXPRESS;Initial Catalog=DataBase;UID=sa;Password=password;" />
</config>
</activerecord>
創建ActiveRecord類
使用ActiveRecord中的配置關鍵字ActiveRecordAttributes、PrimaryKeyAttribute、PropertyAttribute等,為實體類配置表、字段、關系等映射信息。
使用ActiveRecordAttributes配置實體類,關聯映射信息。樣例如下:
默認實體類名與數據庫表同名
[ActiveRecord()]
public class Transport_List : Transport_Department_Base
在實體類中,通過PrimaryKeyAttribute來指定表的主鍵
[PrimaryKey()]
public int Id
在ActiveRecord中通過PropertyAttribute來指定實體類屬性與數據庫中的字段映射。
[Property(“ForReimburse”)]
public string Reimburse_remark
在ActiveRecord中,允許直接對Field進行映射,使用FieldAttribute。
[Field”CheckName”]
public string CheckName
配置關系映射
 
多對一關系可以使用BelongsToAttribute表示。
[BelongsTo("end_point_id")]
public Transport_Location End_point
一對多關系可以使用HasManyAttribute表示。
[HasMany(typeof(Signed_List),Table = "Signed_List",
ColumnKey = transport_list_id", Inverse = true, Cascade = ManyRelationCascadeEnum. AllDeleteOrphan, Lazy = true)]
public IList Signed_Lists
ActiveRecord還支持多對多關系,以及一對一關系。在ActiveRecord中把數據庫表之間的關聯關系采用對象間的聚合關系來表現,然而這卻帶來一系列的性能上的問題。就像在一對多中用到的例子Blog,使用Blog.Find(1)查找了一個Blog對象,也許我們只用到它,但事實它卻把該Blog所關聯的Post對象也讀取出來放在了內存中,于是就需要有一種方法來實現只在需要Post對象的時候框架再自動讀取。
要實現延遲加載,其實只要在HasAndBelongsToMany、HasManyAttribute的特性中使用Lazy=true。另外,使用延遲加載時還需要將當前的Session保存下來,否則ActiveRecord在實現延遲載入時找不到一個NHibernate的ISession而出錯。為了保存當前的Session我們必須使用new SessionScope()。
使用Scope以及schema相關方法
 
Scopes允許優化一系列數據庫操作,以及為代碼塊加入業務語義。一個Scopes中的所有ActiveRecord的數據庫操作都是在同一個數據庫線程中執行。如果使用了延遲加載,則必須使用SessionScope。包括SessionScope,TransactionScope以及Nested Transactions.
使用SessionScope過程如下:
using (new Castle.ActiveRecord.SessionScope())
{
SelectedBizList = new List<Business_List>();
for (int j = 0; j < selectedSheetList.Count ; j++)
{
selectedBiz=Business_List.Find(selectedSheetList[j].Id);
SelectedBizList.Add(selectedBiz);
}
}
使用TransactionScope過程如下:
using (TransactionScope btran = new TransactionScope())
{
try
{ myDriver.Create();
btran.VoteCommit(); }
catch
{ btran.VoteRollBack() }
}
Castle ActiveRecord提供了由實體類生成數據庫表的方法,它其實在底層是封裝了NHibernate.Tool.hbm2ddl中的SchemaExport。
既創建數據庫表的方法都是通過SchemaExport類來完成了,所有的這些方法都在ActiveRecordStarter中提供.
使用HQL查詢
ActiveRecord只提供了Find(id),FindAll()這樣兩個靜態的查詢方法,在實際查詢中比如綜合支撐平臺中對多種業務單的詳細查詢就不能滿足要求了,這方面ActiveRecord為我們提供了HQL語言的支持。HQL全名是Hibernate Query Language,它是一種完全面向對象的查詢語言。
SimpleQuery是一種最簡單的查詢,它直接處理HQL語句,并返回一個集合,沒有復雜的參數處理,具體用法參考下例:
public static Driver[] FindDriversIs_inOrNot(bool is_in)
{ string hql = @"from Driver where Is_in = ? ";
Castle.ActiveRecord.Queries.SimpleQuery query = new Castle.ActiveRecord.Queries.SimpleQuery(typeof(Driver), hql, is_in);
return (Driver[])ActiveRecordBase.ExecuteQuery(query); }
ScalarQuery查詢也是一種簡單的直接處理HQL的查詢,它也沒有復雜的參數處理,只不過返回的值不是集合而是單一的值,具體用法類似SimpleQuery。
HqlBasedQuery是最為強大的Query類,支持跨庫/跨基類聯合查詢;可以使用HqlBasedQuery來實現選定屬性查詢,返回的結果為ArrayList,結構形式與SQL查詢類似,可每行作為一個Object,而后按順序提取字段值,具體用法參考下例:
public static string FindMaxSnOfOuterDriver()
{
string hql = ""; HqlBasedQuery query;
hql = @"select max(dir.Driver_sn) from Driver dir where dir.Is_in = 'False' ";
query = new HqlBasedQuery(typeof(Driver), hql);
IList result= (IList)ActiveRecordBase.ExecuteQuery(query);
if (result == null || result.Count == 0)
return "10000";
else
else return result[0].ToString();
}
小結
根據以上的介紹,利用ActiveRecord數據庫訪問中間件,極大的簡化了數據庫操作,可以擴展數據庫系統的應用范圍。這種中間件不僅適應于局域網,更加適應于未來的基于廣域網的應用程序。ActiveRecord數據訪問中間件不僅跨平臺,而且使用方便,并且擴展性高。上述例子是以微軟的SQL SERVER作為數據庫應用,如要擴展到Oracle或其他數據庫只需更新其相應的.Net插件即可。Castle的ActiveRecord底層將NHibernate封裝了起來,使用起來感覺比Nhibernate方便多了,不用再去生成一個個的映射文件,調試和維護起來都方便了很多。
 
經過在物流倉儲綜合支撐平臺中應用數據訪問中間件,程序的開發周期大大縮短,程序的可維護性,以及可擴展性得到了提高,在信息管理平臺中使用數據訪問中間件將是一個有效的解決方案。
                    
                傳統的數據庫訪問技術對于數據庫操作的復雜性,以及擴展性差等問題已漸漸制約分布式應用集成的需要,利用新技術,研究和開發新的數據庫訪問中間件成為數據庫研究領域的主要方向之一。中間件技術將傳統的客戶機/服務器體系結構擴展為三層體系結構模式,即客戶機-中間件-服務器體系模式。
本文所述系統為物流倉儲綜合支撐平臺,用于支撐多種基本物流業務,包括報關(單證)、存儲、運輸、訂艙等基本業務類型以及由這些基本業務類型所組成的各種復合業務類型。系統采用表示層、業務處理層與數據存儲層三層結構的CS架構,表示層的主要職責是為用戶提供信息以及提供交互。表示層細分為界面外觀層與界面邏輯層。業務邏輯層的主要職責是對用戶提交的輸入指令與數據做校驗,再加工后將數據提交到數據存儲層或將數據存儲層的數據提取后返回給表示層。數據存儲層主要職責是存儲用戶數據。其中數據訪問層與事務處理層,使用Castle ActiveRecord框架作為數據庫持久層,框架提供對數據訪問層與事務處理層的封裝。
數據訪問中間件定義
中間件為可以為其他程序員服用、實現特定功能接口的程序包或服務。中間件在操作系統軟件,網絡和數據庫之上,應用軟件之下,總的作用是為處于上層的應用程序提供開發環境,幫助用戶高效、靈活的開發和集成更加復雜的應用軟件。IDC對中間件的定義為:中間件是一種獨立的系統軟件或服務程序,分布式應用軟件借助這種軟件在不同的技術之間共享資源,中間件定位于客戶機服務器的操作系統之上,管理計算機資源和網絡通信。按照IDC的分類方法,中間件可分為六類:終端仿真、數據訪問中間件、遠程過程調用中間件、消息中間件、交易中間件、對象中間件。
本文涉及的數據訪問中間件為中間件的一種,是指一切連接應用程序和數據庫的軟件,位于客戶機服務器的操作系統之上,通過使用統一接口提供對運行在多種平臺上的不同數據庫的訪問。通過使用數據訪問中間件,可擴展性得到了大大的增強,可以最大限度的不影響上層的應用程序的結構,減少系統維護的難度。由于對于數據庫的操作都被封裝在數據庫訪問中間件,用戶對數據的管理實現了對數據庫操作的透明性。
本文所述系統使用的數據庫訪問中間件為Castle .Net 中的額ActiveRecord組件,它是一個輕量級的ORM組件,它在底層封裝了NHibernate. NHibernate是一個基于.Net,用于關系數據庫的對象持久化類庫,它是著名的Hibernate的.Net版本,采用xml配置文件進行關系的映射。在ActiveRecord中,則對這種方式進行了進一步的封裝,采用特性(Attribute)的方式進行映射。
數據訪問中間件實現
本系統采用表示層、業務處理層與數據存儲層三層結構的CS架構。如下圖所示為該系統項目軟件結構如圖一所示。

由于本項目采用C/S架構,故僅主要使用Castle中的數據訪問ORM框架Castle ActiveRecord。Castle ActiveRecord是Castle中提供的一個輕量級數據訪問框架,它在底層封裝了NHibernate的操作,使用特性來代替映射文件,從而提供非常簡潔的O/R映射(一對一、一對多,多對多關系等均可以表達)。同時,它還實現了對象的最基本的CRUD操作,這在很大程度上減少了開發的工作量。另外,ActiveRecord支持HQL(Hibernate Query Language ),使開發人員可以自定義一些復雜查詢。其他特性:多數據庫連接、支持事務處理、維護方便性。提供對數據訪問層與事務處理層的封裝。
數據訪問中間件的配置
ActiveRecord在底層封裝了NHibernate,在框架啟動時需要指定相關的配置信息。可以使用自己的XML文件來保存配置信息,例如有一個AppConfig.xml的文件。
<activerecord>
<config>
<add
key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
<add
key="hibernate.dialect" value="NHibernate.Dialect.MsSql2005Dialect" />
<add key="hibernate.connection.provider"value="NHibernate.Connection.DriverConnectionProvider" />
<add
key="hibernate.connection.connection_string" value="Data Source=.\SQLEXPRESS;Initial Catalog=DataBase;UID=sa;Password=password;" />
</config>
</activerecord>
創建ActiveRecord類
使用ActiveRecord中的配置關鍵字ActiveRecordAttributes、PrimaryKeyAttribute、PropertyAttribute等,為實體類配置表、字段、關系等映射信息。
使用ActiveRecordAttributes配置實體類,關聯映射信息。樣例如下:
默認實體類名與數據庫表同名
[ActiveRecord()]
public class Transport_List : Transport_Department_Base
在實體類中,通過PrimaryKeyAttribute來指定表的主鍵
[PrimaryKey()]
public int Id
在ActiveRecord中通過PropertyAttribute來指定實體類屬性與數據庫中的字段映射。
[Property(“ForReimburse”)]
public string Reimburse_remark
在ActiveRecord中,允許直接對Field進行映射,使用FieldAttribute。
[Field”CheckName”]
public string CheckName
配置關系映射
多對一關系可以使用BelongsToAttribute表示。
[BelongsTo("end_point_id")]
public Transport_Location End_point
一對多關系可以使用HasManyAttribute表示。
[HasMany(typeof(Signed_List),Table = "Signed_List",
ColumnKey = transport_list_id", Inverse = true, Cascade = ManyRelationCascadeEnum. AllDeleteOrphan, Lazy = true)]
public IList Signed_Lists
ActiveRecord還支持多對多關系,以及一對一關系。在ActiveRecord中把數據庫表之間的關聯關系采用對象間的聚合關系來表現,然而這卻帶來一系列的性能上的問題。就像在一對多中用到的例子Blog,使用Blog.Find(1)查找了一個Blog對象,也許我們只用到它,但事實它卻把該Blog所關聯的Post對象也讀取出來放在了內存中,于是就需要有一種方法來實現只在需要Post對象的時候框架再自動讀取。
要實現延遲加載,其實只要在HasAndBelongsToMany、HasManyAttribute的特性中使用Lazy=true。另外,使用延遲加載時還需要將當前的Session保存下來,否則ActiveRecord在實現延遲載入時找不到一個NHibernate的ISession而出錯。為了保存當前的Session我們必須使用new SessionScope()。
使用Scope以及schema相關方法
Scopes允許優化一系列數據庫操作,以及為代碼塊加入業務語義。一個Scopes中的所有ActiveRecord的數據庫操作都是在同一個數據庫線程中執行。如果使用了延遲加載,則必須使用SessionScope。包括SessionScope,TransactionScope以及Nested Transactions.
使用SessionScope過程如下:
using (new Castle.ActiveRecord.SessionScope())
{
SelectedBizList = new List<Business_List>();
for (int j = 0; j < selectedSheetList.Count ; j++)
{
selectedBiz=Business_List.Find(selectedSheetList[j].Id);
SelectedBizList.Add(selectedBiz);
}
}
使用TransactionScope過程如下:
using (TransactionScope btran = new TransactionScope())
{
try
{ myDriver.Create();
btran.VoteCommit(); }
catch
{ btran.VoteRollBack() }
}
Castle ActiveRecord提供了由實體類生成數據庫表的方法,它其實在底層是封裝了NHibernate.Tool.hbm2ddl中的SchemaExport。
既創建數據庫表的方法都是通過SchemaExport類來完成了,所有的這些方法都在ActiveRecordStarter中提供.
使用HQL查詢
ActiveRecord只提供了Find(id),FindAll()這樣兩個靜態的查詢方法,在實際查詢中比如綜合支撐平臺中對多種業務單的詳細查詢就不能滿足要求了,這方面ActiveRecord為我們提供了HQL語言的支持。HQL全名是Hibernate Query Language,它是一種完全面向對象的查詢語言。
SimpleQuery是一種最簡單的查詢,它直接處理HQL語句,并返回一個集合,沒有復雜的參數處理,具體用法參考下例:
public static Driver[] FindDriversIs_inOrNot(bool is_in)
{ string hql = @"from Driver where Is_in = ? ";
Castle.ActiveRecord.Queries.SimpleQuery query = new Castle.ActiveRecord.Queries.SimpleQuery(typeof(Driver), hql, is_in);
return (Driver[])ActiveRecordBase.ExecuteQuery(query); }
ScalarQuery查詢也是一種簡單的直接處理HQL的查詢,它也沒有復雜的參數處理,只不過返回的值不是集合而是單一的值,具體用法類似SimpleQuery。
HqlBasedQuery是最為強大的Query類,支持跨庫/跨基類聯合查詢;可以使用HqlBasedQuery來實現選定屬性查詢,返回的結果為ArrayList,結構形式與SQL查詢類似,可每行作為一個Object,而后按順序提取字段值,具體用法參考下例:
public static string FindMaxSnOfOuterDriver()
{
string hql = ""; HqlBasedQuery query;
hql = @"select max(dir.Driver_sn) from Driver dir where dir.Is_in = 'False' ";
query = new HqlBasedQuery(typeof(Driver), hql);
IList result= (IList)ActiveRecordBase.ExecuteQuery(query);
if (result == null || result.Count == 0)
return "10000";
else
else return result[0].ToString();
}
小結
根據以上的介紹,利用ActiveRecord數據庫訪問中間件,極大的簡化了數據庫操作,可以擴展數據庫系統的應用范圍。這種中間件不僅適應于局域網,更加適應于未來的基于廣域網的應用程序。ActiveRecord數據訪問中間件不僅跨平臺,而且使用方便,并且擴展性高。上述例子是以微軟的SQL SERVER作為數據庫應用,如要擴展到Oracle或其他數據庫只需更新其相應的.Net插件即可。Castle的ActiveRecord底層將NHibernate封裝了起來,使用起來感覺比Nhibernate方便多了,不用再去生成一個個的映射文件,調試和維護起來都方便了很多。
經過在物流倉儲綜合支撐平臺中應用數據訪問中間件,程序的開發周期大大縮短,程序的可維護性,以及可擴展性得到了提高,在信息管理平臺中使用數據訪問中間件將是一個有效的解決方案。