什末是等級化數據集?我們為什末要關注它?
等級化數據集并不是一個新的概念。 在客戶控制信息系統的事務化數據表單中,目錄的文件中, 以及常用的JAVA對象中都存在著等級化數據集, 同樣的,它也很明顯的存在于XML中。在2001早期的XML 雜志中, 我發表了一個觀點-程序員會受益于等級化數據抽,即使他們的很多數據源是顯著相關的(比如數據庫包括MySQL, Oracle, SQL Server, DB2, 等等。)。
在.NET世界中有一個相似的觀點來自于“數據集”概念。雖然在我提議的等級化數據集和微軟的數據集有很重要的不同,但是,很顯然,等級化數據集通過豐富的細節化處理增強了相關的抽象提取。
這篇文章描述了Java API使用的分等級的數據集結構。不同于二年前XML 學報參考,您現在將會有可執行的代碼片斷,通過運行它,可以體驗開始利用分等級的數據集。雖然程序員能使用Java編碼來訪問各種各樣的數據源,以及構建最后的分等級的數據集,這篇文章可以通過簡單地組成預構造的關系適配器,讓您很容易的構建這些分等級的數據集。關系適配器包括文件閱讀器、SQL閱讀器、存儲過程的閱讀器,等等。
您大概會問:"這些分等級的數據集的好處在哪里?",雖然他們目前的作用還不是主導地位的,但是在編程界,等級結構數據集是相當有用的。對于初學者,一個完整的HTML頁面所應具有的數據價值可以由一個等級結構數據集來滿足。在一個MVC 模型中,一個servlet 控制器 能提供一個等級制度的數據集給JSP 頁面,這個頁面可以輕松的作它需要做的。 在數據準備方面,它能被轉換成XML 并直接地通過servlet控制器返回到訪問者。在應用方面,等級結構數據集能被轉換成Excel 文檔。在格式方面,等級結構數據集能重定向為一個報告引擎或一個支持XML 數據的繪制圖表的引擎。
雖然文章的主要焦點是面向Java 程序員的Java 編程API,等級結構數據集能被非Non-Java 程序員相當有效地使用,直接地從關系數據庫和其它數據源,同過使用像Tomcat這樣的J2EE 服務器獲得XML 、HTML ,或Excel 格式。閑言少講,讓我們研究一下等級結構數據集的結構,以及看看這些數據集是怎樣被獲得的(當放松一下您的編程肌肉) 。
等級化數據結構
一種等級化數據結構能概念性地描述為如同Java API ,或XML ,或某一其它格式。它最容易形象化地作為XML 。
<AspireDataSet>
<!—一組在根級別的key value 對-->
<key1>val1</key1>
<key2>val2</key2>
<!—一組指定的循環 -->
<loop name="loop">
</loop>
<loop name="loop2">
</loop>
</AspireDataSet>
這是一套key/value 對。給出的這套key/value 對能產生n 個獨立的循環。各個循環本質上來說是一個數據表。這里,術語"循環" 與"表?±是同義的。 我沒有使用"表" 是因為人們可能會根據字面意思來只采用表作為從關系表中取出的的唯一數據。被提及是行的集合(RowSet) ,讓我們更加接近地看一下循環的結構:
<loop name="loopname">
<row>
<!--一組key value 對-->
<key1>val1</key1>
<key2>val2</key2>
<!--一組指定的循環-->
<loop name="loopname1">
</loop>
<!--一組指定的循環-->
<loop name="loopname2">
</loop>
</row>
<row>
</row>
</loop>
這里唯一的沒有配對的是列的結構。列是期望的key/value對的集合。這里列不僅包括key/value 對,而且包括另外的一個n個獨立循環的遞歸集。引伸一下可以生成任意數量深度的樹。(或者我應該說,任意的高度!)
Java中的等級化數據結構
在我用XML顯示等級化數據的時候,有一種可能性,就是人們也許采取一個等級化數據集逐字的訪問XML數據,繼而,逐字地使用DOM,繼而,在JVM 里面消耗很多的內存。不過不必驚慌,等級化數據集有它自己的Java API,從而可以不使用DOM。多數的時候只是向前遍歷加載數據樹。下面是一個使用Java API 處理一個等級化數據集的例子:
package com.ai.htmlgen;
import com.ai.data.*;
/**
* 代表了一個等級化數據集。
* 一個hds 是一個行的集合。
* 你可以通過ILoopForwardIterator枚舉這些行
* 你可以通過IMetaData 枚舉各個列。
* 一個hds 也是一個基于當前行得循環集。
*/
public interface ihds extends ILoopForwardIterator
{
/**
*返回父級接口
* 如果沒有父級接口則返回NULL
*/
public ihds getParent() throws DataException;
/**
* 基于當前行返回一系列的子循環名字。ILoopForwardIteraor 確當前行是什末。
*
*
* @see ILoopForwardIterator
*/
public IIterator getChildNames() throws DataException;
/**
* 通過給定的名字返回一個ihds 類型的Java子對象
*/
public ihds getChild(String childName) throws DataException;
/**
返回一個列,這跟對一個行集合進行求和,求平均很類似。
*/
public String getAggregatevalue(String keyname) throws DataException;
/**
返回這個循環或者表的列名字。
* @see IMetaData
*/
public IMetaData getMetaData() throws DataException;
/**
釋放所有數據或表格循環使用的資源。
*/
public void close() throws DataException;
}
簡而言之,Javaihds 接口描述了“面向等級數據集的接口?!边@個API允許你使用循環遞歸調用。在運行時,有個選項指定只有當他們被要求的時候才加載這些循環。它也能夠假定是僅僅向前還是隨機遍歷。在往下繼續以前, 讓我來介紹兩個另外該API使用的接口:ILoopForwardIterator 和ImetaData。
如何在HDS中移動遍歷一系列的行:ILoopForwardIterator
package com.ai.htmlgen;
import com.ai.data.*;
public interface ILoopForwardIterator
{
/**
* 根據匹配的鑰匙從當前的行中獲取相應的值
*/
public String getvalue(final String key);
public void moveToFirst() throws DataException;
public void moveToNext() throws DataException;
public boolean isAtTheEnd() throws DataException;
}
IMetaData: 用來讀取列名
package com.ai.data;
public interface IMetaData
{
public IIterator getIterator();
public int getColumnCount();
public int getIndex(final String attributeName)
throws FieldNameNotFoundException;
}
你如何獲取一個等級數據集, 從而你可以使用它?
現在我們知道了等級化數據集的結構, 你如何來控制它呢?根據我的經驗, 這個在Aspire下會很容易。下面是所列的步驟:
1. 學習Aspire的基礎。
2. 為你的等級化數據集創建一個定義文件。
3. 在Java代碼中調用你得定義文件從而獲取ihds。
下面對每一步進行詳細的介紹。
閱讀Aspire JAR的用法基礎
Aspire 是一個小的JAR 文件,它可以直接運行, 特別的它可以被一個應用程序服務器調用,例如Tomcat。Aspire的核心是一套配置文件, 在這些文件中你可以通過Java類術語和這些類的參數聲明數據訪問機制。Aspire 將運行那些Java類并且返回結果對象。等級化數據集并非例外。
O'Reilly的一篇早期文章介紹了Aspire:"對于Tomcat的開發者來說, Aspire可以作為JAR"它會通過定義數據庫和調用SQL以及存儲過程來讓你熟悉這些運作,就像配置和初始化Aspire一樣。
為你的等級化數據集創建一個定義文件。
下面是一個等級化數據集的簡單定義:
###################################
# ihdsTest 數據定義:1區
###################################
request.ihdsTest.className=com.ai.htmlgen.DBHashTableFormHandler1
request.ihdsTest.loopNames=works
#2區
request.ihdsTest.works.class_request.className=com.ai.htmlgen.GenericTableHandler6
request.ihdsTest.works.loopNames=childloop1
request.ihdsTest.works.query_request.className=com.ai.data.RowFileReader
request.ihdsTest.works.query_request.filename=aspire:\\samples
\\pop-table-tags\\properties\\pop-table.data
#3區
request.childloop1.class_request.classname=com.ai.htmlgen.GenericTableHandler6
request.childloop1.query_request.classname=com.ai.data.RowFileReader
request.childloop1.query_request.filename=aspire:\\samples\\pop-table-tags
\\properties\\pop-table.da
原文轉自:http://www.anti-gravitydesign.com