精彩的人生

          好好工作,好好生活

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks
           

          簡單地說,SDO是一種數(shù)據(jù)應(yīng)用程序開發(fā)框架,它包括一個體系結(jié)構(gòu)和相應(yīng)的 API。SDO 能夠?qū)崿F(xiàn)以下操作:

          • 簡化 J2EE 數(shù)據(jù)編程模型。
          • 抽象面向服務(wù)體系結(jié)構(gòu)(SOA)中的數(shù)據(jù)。
          • 統(tǒng)一數(shù)據(jù)應(yīng)用程序的開發(fā)。
          • 支持和集成 XML。
          • 結(jié)合 J2EE 模式和最佳實踐。

          在這篇介紹 SDO 框架的文章中,我們將嘗試著解釋 SDO 背后的動機,以及 SDO 與其他規(guī)范的區(qū)別,然后描述 SDO 的組成,最后,通過一個示例 SDO 應(yīng)用程序說明 SDO 的用法。

          為什么要使用 SDO?
          對于服務(wù)數(shù)據(jù)對象(SDO),大多數(shù)開發(fā)人員要問的第一個問題就是為什么要使用 SDO。難道 J2EE 本身還不夠龐大、不夠復(fù)雜(而且難以掌握)嗎?Java 環(huán)境中不是已經(jīng)有其他支持 XML 的框架了嗎?所幸的是,該問題的答案能夠讓我們多數(shù)人感到滿意:SDO 是作為簡化 J2EE 數(shù)據(jù)編程模型的方法出現(xiàn)的,它能夠讓 J2EE 開發(fā)人員把更多的時間用于應(yīng)用程序的業(yè)務(wù)邏輯。

          服務(wù)數(shù)據(jù)對象框架為數(shù)據(jù)應(yīng)用程序開發(fā)提供了統(tǒng)一的框架。通過 SDO,您不需要熟悉特定于技術(shù)的 API,就能訪問和利用數(shù)據(jù)。您只需要知道一種 API,即 SDO API,它允許您處理來自多種數(shù)據(jù)源的數(shù)據(jù),其中包括關(guān)系數(shù)據(jù)庫、實體 EJB 組件、XML 頁面、Web 服務(wù)、Java Connector Architecture、JavaServer Pages 頁面等。

          注意,我們使用了 框架這一詞。這是比照 Eclipse 框架的說法。由于設(shè)計的基礎(chǔ)堅固而且可以擴展,所以 Eclipse 能夠集成各種工具。與此類似,對于采用 SDO 的應(yīng)用程序,SDO 也是一種框架,這類應(yīng)用程序在 SDO 模型上是一致的。

          與其他某些數(shù)據(jù)集成模型不同的是,SDO 沒有停留在數(shù)據(jù)抽象上。SDO 框架還結(jié)合了很多 J2EE 模式和最佳實踐,從而使應(yīng)用程序很容易結(jié)合經(jīng)過驗證的體系結(jié)構(gòu)和設(shè)計。比方說,今天的多數(shù) Web 應(yīng)用程序百分之百的時間沒有(或不能)連接到后端系統(tǒng),因此 SDO 支持不連接的編程模型。同樣的,今天的應(yīng)用程序往往非常復(fù)雜,包含很多層次。如何存儲數(shù)據(jù)、如何發(fā)送數(shù)據(jù)、如何在 GUI 框架中將它們提供給終端用戶?SDO 編程模型提供的應(yīng)用模式能夠清晰地劃分不同的問題。

          XML 在分布式應(yīng)用程序中日漸普及。比如,XML Schema (XSD) 被用來定義應(yīng)用程序數(shù)據(jù)格式中的業(yè)務(wù)規(guī)則。XML 本身也可以用于改進交互性:Web 服務(wù)使用基于 XML 的 SOAP 作為消息格式。XML 是推動 SDO 的一個重要原因,SDO 框架支持并集成了 XML。

          各種技術(shù)的比較
          前面已經(jīng)提到,SDO 并不是提出解決分布式應(yīng)用程序中數(shù)據(jù)集成問題的惟一技術(shù)。下面將分別討論 SDO 和類似的編程框架 JDO、JAXB 和 EMF 的優(yōu)劣。

          SDO 和 WDO
          Web 數(shù)據(jù)對象(或 WDO)是隨著 IBM WebSphere? Application Server 5.1 和 IBM WebSphere Studio Application Developer 5.1.2 發(fā)布的 SDO 早期版本的名稱。如果使用過 WebSphere Studio 5.1.2,那么您對 SDO 可能已經(jīng)有所了解,雖然您可能習(xí)慣看到將它標(biāo)記為 WDO,比如在數(shù)據(jù)庫的名字中。忘掉 WDO 吧,它現(xiàn)在的名字是 SDO!

          SDO 和 JDO
          JDO 代表 Java Data Object(Java 數(shù)據(jù)對象)。JDO 已經(jīng)通過 Java 社區(qū)進程(JCP)標(biāo)準(zhǔn)化了 1.0 版,2003 年 5 月推出了維護版 1.0.1,現(xiàn)在已經(jīng)為 2.0 版成立了 JCP 專家組。JDO 針對 Java 環(huán)境中的數(shù)據(jù)編程提供了一種通用 API,用于訪問存儲在不同數(shù)據(jù)源中的數(shù)據(jù),如數(shù)據(jù)庫、文件系統(tǒng)或者事務(wù)處理系統(tǒng)。JDO 保持了 Java 對象(圖)之間的關(guān)系,同時允許對數(shù)據(jù)的并發(fā)訪問。

          JDO 希望簡化和統(tǒng)一 Java 數(shù)據(jù)編程,以便開發(fā)人員能夠?qū)W⒂跇I(yè)務(wù)邏輯,而不是底層的技術(shù),從這一點上說,其目標(biāo)和 SDO 是相同的。但主要的區(qū)別在于,JDO 僅考慮持久性問題(J2EE 數(shù)據(jù)層或者企業(yè)信息系統(tǒng)(EIS)層),而 SDO 更具一般性,關(guān)注的是不同 J2EE 層次間數(shù)據(jù)流的表示,比如表示層和業(yè)務(wù)層。

          有趣的是,SDO 可以結(jié)合 JDO 一起使用,JDO 作為數(shù)據(jù)源,SDO 來訪問它,這就是 Data Transfer Object(數(shù)據(jù)傳輸對象,DTO)設(shè)計模式的具體運用。同樣,SDO 也可以結(jié)合實體 EJB 組件和 Java Connector Architecture(Java 連接器體系結(jié)構(gòu),JCA)使用,目的是提供統(tǒng)一的數(shù)據(jù)訪問。

          SDO 和 EMF
          EMF 代表 Eclipse Modeling Framework(Eclipse 建??蚣埽MF 根據(jù)使用 Java 接口、XML Schema 或者 UML 類圖定義的數(shù)據(jù)模型生成統(tǒng)一的元模型(稱為 Ecore),可以將元模型與框架結(jié)合在一起使用,創(chuàng)建高質(zhì)量的模型實現(xiàn)。EMF 提供了持久性、一個有效的反射類屬對象操縱 API 和一個變更通知框架。EMF 還包括用來構(gòu)建 EMF 模型編輯器的一般的重用類。

          EMF 和 SDO 都可以處理數(shù)據(jù)表示。事實上,IBM 的 SDO 參考實現(xiàn)就是一種 SDO 的 EMF 實現(xiàn),后面我們還要用到該實現(xiàn)。還可以根據(jù) UML 模型定義或者 SDO 本身,用 EMF 代碼生成來創(chuàng)建 SDO 實現(xiàn)的某些部分。SDO 實現(xiàn)基本上是 EMF 中的一小層(方面),它是作為 EMF 項目的一部分打包和提供的。關(guān)于 EMF 的更多信息,請參閱 參考資料。

          SDO 和 JAXB
          JAXB 代表 Java API for XML Data Binding(XML 數(shù)據(jù)綁定 Java API)。JAXB 1.0 在 2003 年 1 月由 JCP 發(fā)布。JCP 專家組已經(jīng)制定了 2.0 版的初步草案。JAXB 是關(guān)于 XML 數(shù)據(jù)綁定的,也就是說,將 XML 數(shù)據(jù)表示成內(nèi)存中的 Java 對象。作為 Java 語言的 XML 綁定框架,JAXB 可以節(jié)約解析和創(chuàng)建 XML 文檔的時間。(事實上,通過它,您完全不需要和 XML 打交道。)JAXB 為您執(zhí)行編組/序列化(Java 到 XML)和解組/并行化(XML 到 Java)。

          SDO 定義了自己的 Java 綁定框架,但是走得還要遠(yuǎn)一些。JAXB 僅關(guān)注 Java 到 XML 的綁定,而綁定到 SDO 的不僅僅是 XML 數(shù)據(jù)。如前所述,SDO 提供了對不同類型數(shù)據(jù)的統(tǒng)一訪問,XML 僅是其中的一種數(shù)據(jù)類型。SDO 還提供了靜態(tài)和動態(tài) API *,而 JAXB 僅提供了靜態(tài)綁定。

          * 注意,本文中示例應(yīng)用程序僅使用了動態(tài) SDO,雖然 EMF 代碼生成器也為數(shù)據(jù)對象的靜態(tài)代碼生成提供了完整的支持。

          SDO 和 ADO .NET
          ADO 代表 ActiveX Data Objects(ActiveX 數(shù)據(jù)對象),但是在 .NET 上下文中,其含義已經(jīng)發(fā)生了變化。ADO .NET 提供了 .NET 框架下不同層次間的統(tǒng)一數(shù)據(jù)訪問機制。

          ADO .NET 和 SDO 具有相同的動機,都是用來支持 XML 和分布在多個層上的應(yīng)用程序。除了技術(shù)性的差異外,這兩項技術(shù)主要的不同在于:ADO .NET 用于 Microsoft .NET 平臺,是一種私有的技術(shù);而 SDO 用于 Java (J2EE) 平臺,通過 Java 社區(qū)進程實現(xiàn)標(biāo)準(zhǔn)化。

          SDO 的組成部分
          這一節(jié)將介紹 SDO 的體系結(jié)構(gòu)。我們將介紹組成框架的不同組成部分和它們之間的協(xié)作。首先要討論的三個組成部分之一是 SDO 的“概念性”特征,API 中沒有對應(yīng)的接口。

          SDO 客戶機
          SDO 客戶機使用 SDO 框架處理數(shù)據(jù)。SDO 客戶機使用的不是特定于技術(shù)的 API 和框架,而是 SDO 編程模型和 API。SDO 客戶機處理 SDO 數(shù)據(jù)圖(參見 圖 1),不需要了解所處理的數(shù)據(jù)是如何持久保存或者序列化的。

          Data 中介服務(wù)
          數(shù)據(jù)中介服務(wù)(DMS)負(fù)責(zé)從數(shù)據(jù)源創(chuàng)建數(shù)據(jù)圖、依據(jù)數(shù)據(jù)圖的變化更新數(shù)據(jù)源。數(shù)據(jù)中介框架不屬于 SDO 1.0 規(guī)范,換句話說,SDO 1.0 沒有涉及具體的 DMS。常見的 DMS 有 JDBC DMS、實體 EJB DMS 和 XML DMS 等。

          數(shù)據(jù)源
          數(shù)據(jù)源不限于后端數(shù)據(jù)源(如持久存儲數(shù)據(jù)庫)。數(shù)據(jù)源以自己的格式保存數(shù)據(jù)。只有 DMS 訪問數(shù)據(jù)源,SDO 應(yīng)用程序不訪問數(shù)據(jù)源。SDO 應(yīng)用程序可能只使用數(shù)據(jù)圖中的數(shù)據(jù)對象。

          下面介紹的每個組件對應(yīng)于 SDO 編程模型的一個 Java 接口。SDO 參考實現(xiàn)(請參閱 參考資料)提供了這些接口基于 EMF 的實現(xiàn)。

          數(shù)據(jù)對象
          數(shù)據(jù)對象是 SDO 的基本組件。事實上,它們是規(guī)范名稱中的 服務(wù)數(shù)據(jù)對象。數(shù)據(jù)對象是結(jié)構(gòu)化數(shù)據(jù)的 SDO 表示。數(shù)據(jù)對象是通用的,它們提供了 DMS 創(chuàng)建的結(jié)構(gòu)化數(shù)據(jù)的公共視圖。比方說,雖然 JDBC DMS 需要知道持久性技術(shù)(比如關(guān)系數(shù)據(jù)庫),以及如何配置和訪問數(shù)據(jù),SDO 客戶機不需要了解這些細(xì)節(jié)。數(shù)據(jù)對象在屬性中保存它們的“數(shù)據(jù)”(稍后還要討論屬性)。數(shù)據(jù)對象提供了易于使用的創(chuàng)建和刪除方法(帶有不同簽名的 createDataObject()delete() ),獲得自身類型(實例類、名稱、屬性和名稱空間)的反射方法。數(shù)據(jù)對象都鏈接在一起,包含在數(shù)據(jù)圖中。

          數(shù)據(jù)圖
          數(shù)據(jù)圖提供了數(shù)據(jù)對象樹的容器。數(shù)據(jù)圖由 DMS 生成,供 SDO 客戶機使用。修改后,數(shù)據(jù)圖被回傳給 DMS 更新數(shù)據(jù)源。SDO 客戶機可以遍歷數(shù)據(jù)圖,讀取和修改數(shù)據(jù)圖中的數(shù)據(jù)對象。SDO 是一種 無連接的體系機構(gòu),因為 SDO 客戶機與 DMS 和數(shù)據(jù)源沒有連接,所以 SDO 客戶機看到的只有數(shù)據(jù)圖。此外,數(shù)據(jù)圖可以包含表示不同數(shù)據(jù)源中數(shù)據(jù)的對象。數(shù)據(jù)圖包含一個根數(shù)據(jù)對象、與根關(guān)聯(lián)的所有數(shù)據(jù)對象和變更摘要(change summary,參見本文后面的敘述)。當(dāng)在應(yīng)用程序組件(比如服務(wù)調(diào)用期間的 Web 服務(wù)請求者和提供者)之間進行傳輸、組件到 DMS 的傳輸(或者保存到磁盤)的時候,數(shù)據(jù)圖被序列化為 XML。SDO 規(guī)范提供了序列化的 XML Schema。圖 1 顯示了一個 SDO 數(shù)據(jù)圖。

          圖 1. SDO 數(shù)據(jù)圖
          SDO 數(shù)據(jù)圖

          變更摘要
          變更摘要包含在數(shù)據(jù)圖中,表示對 DMS 返回的數(shù)據(jù)圖的修改。變更摘要最初是空的(數(shù)據(jù)圖剛返回客戶機的時候),隨著數(shù)據(jù)圖的變化逐漸填充。在后臺更新時,DMS 使用變更摘要將修改應(yīng)用于數(shù)據(jù)源。變更摘要提供了數(shù)據(jù)圖中被修改的屬性(包括原來的值)、新增和刪除的數(shù)據(jù)對象的列表,從而使 DMS 以遞增方式高效地更新數(shù)據(jù)源。只有當(dāng)變更摘要日志功能被激活時,才會將信息添加到數(shù)據(jù)圖的變更摘要中。變更摘要提供了讓 DMS 打開和關(guān)閉日志功能的方法,后面的例子中還將詳細(xì)對其進行介紹。

          屬性、類型和序列
          數(shù)據(jù)對象用一系列屬性保存其內(nèi)容。每個屬性都有一個類型,該類型既可以是基本類型(如 int )這樣的屬性類型,也可以是通用數(shù)據(jù)類型(如 Date ),如果引用的話,還可以是其他數(shù)據(jù)對象類型。每個數(shù)據(jù)對象都為屬性提供了訪問和設(shè)置方法(getter 和 setter)。這些訪問器方法有不同的重載版本,可以通過傳遞屬性名( String )、編號( int )或者屬性元對象本身來訪問屬性。String 訪問器還允許使用類 XPath 的語法訪問屬性。比如,可以對公司數(shù)據(jù)對象調(diào)用 get("department[number=123]") 來訪問編號為 123的第一個部門。序列更加高級,可以保持不同種類的屬性-值對列表的順序。

          SDO 和示例安裝
          我們已經(jīng)講了很多的概念和理論,現(xiàn)在要進行一些實際操作了。好消息是您馬上就能使用 SDO,而且是免費的。這一節(jié)將介紹一個 SDO 示例應(yīng)用程序,它將在 SDO 的 IBM 參考實現(xiàn)上運行,這個參考實現(xiàn)是 Eclipse Modeling Framework (EMF) 的一部分。我們首先將說明如何安裝 EMF 2.0.1(包括 SDO),然后將介紹如何設(shè)置本文提供的示例應(yīng)用程序。

          安裝 EMF 2.0.1
          如果已經(jīng)安裝了 EMF 2.0.1,或者知道怎么安裝,那么請?zhí)^這一節(jié),直接閱讀下一節(jié)。

          IBM SDO 1.0 實現(xiàn)和 EMF 2.0.1 一起打包。要使用 SDO,則需要安裝 EMF 2.0.1 *。您可以按照 EMF 站點上的說明使用 Eclpise 更新管理器,也可以按照下面的步驟操作。

          *EMF 2.0.0 中也包含 SDO 1.0 的實現(xiàn)。

          EMF 主頁中的“快速導(dǎo)航”部分可以找到下載鏈接頁面,選擇下載“v2.x: EMF 和 SDO”。安裝 EMF 之前一定要閱讀安裝要求。安裝 EMF 2.0.1 之前至少要安裝了 Eclipse 3.0.1 和 Java Development Kit (JDK) 1.4。一定要選擇 EMF 2.0.1 發(fā)行版本。打包類型建議選擇“All”:emf-sdo-xsd-SDK-2.0.1.zip,這樣,就可以在一個文件中找到源代碼、運行文件和文檔。如果愿意,還可以下載 SDO 的最小安裝包“EMF & SDO RT”:emf-sdo-runtime-2.0.1.zip。

          在解壓 Eclipse 的目錄中解壓 zip 文件(壓縮包中的文件組織結(jié)構(gòu)為 eclipse/plugins/...)。啟動 Eclipse,然后選擇 Help>About the Eclipse Platform,檢查 EMF 是否安裝成功。單擊 Plug-in Details按鈕,確保 org.eclipse.emf.* 插件在 2.0.1 層次上。有 6 個與 SDO 有關(guān)的插件:

          • org.eclipse.emf.commonj.sdo
          • org.eclipse.emf.ecore.sdo
          • org.eclipse.emf.ecore.sdo.doc
          • org.eclipse.emf.ecore.sdo.edit
          • org.eclipse.emf.ecore.sdo.editor
          • org.eclipse.emf.ecore.sdo.source

          運行時只需要兩個插件: org.eclipse.emf.commonj.sdoorg.eclipse.emf.ecore.sdo ,如果選擇僅安裝運行時插件,那么您只能看到這兩個插件。這樣就完成了 EMF 的安裝。

          安裝示例 SDO 應(yīng)用程序
          下一步是在工作區(qū)中添加本文所用的 SDO 示例應(yīng)用程序,步驟如下:

          1. 啟動 Eclipse 并創(chuàng)建一個新的 Plug-In Project。
          2. 將項目命名為 SDOSample,選擇源文件夾 src和輸出文件夾 bin,建立 Java 源代碼。
          3. 單擊 Next。
          4. 取消選擇“Generate the Java class that controls the plug-in's life cycle(生成控制插件生命期的 Java 類)”選項并單擊 Finish

          然后,單擊本文頂端或底端的 Code圖標(biāo)(或者參閱 下載部分)下載 j-sdoSample.zip,并將其解壓縮到 SDOSample 目錄中(在 Eclipse 窗口中選擇 Import... >Zip file)。一定要保留文件夾結(jié)構(gòu)并覆蓋原來的文件,這樣,就可以用 j-sdoSample.zip 中的文件代替 SDOSample 項目。

          注意:SDOSample 是作為 Eclipse 插件項目打包的,因此不需要自己設(shè)置庫依賴關(guān)系。但是,在本例中,只包含 Java 代碼,如果在 CLASSPATH 中包含 EMF 和 SDO 庫(JAR 文件),也可將 SDOSample 作為獨立的應(yīng)用程序運行。

          環(huán)境設(shè)置應(yīng)該與下面截屏圖中的類似。

          圖 2. Eclipse 環(huán)境
          Eclipse 環(huán)境

          現(xiàn)在開始使用這個示例 SDO 應(yīng)用程序。

          一個簡單的 SDO 應(yīng)用程序
          本文后面將使用的示例應(yīng)用程序從功能上說很有限,但它可以幫助您更好地理解 SDO。該應(yīng)用程序包括兩部分,分別放在兩個包中:dms 和 client。

          SDO 1.0 沒有規(guī)定標(biāo)準(zhǔn) DMS API。因此我們?yōu)檫@個例子設(shè)計了自己的 DMS 接口,它包含兩個方法,如清單 1 所示。

          清單 1. DMS 接口
          
          /**
           * A simple Data Mediator Service (DMS) that builds
           * SDO Data Graphs of Employees and updates
           * a backend data source according to a Data Graph. 
           */
          public interface EmployeeDMS
          {
            /**
             * @param employeeName the name of the employee.
             * @return an SDO Data Graph with Data Objects for
             * that employee's manager, that employee,
             * and that employee's "employees".
             */
            DataGraph get(String employeeName);
          
            /**
             * updates backend data source according to dataGraph.
             * @param dataGraph Data Graph used to update data source.
             */
            void update(DataGraph dataGraph);
          }
          

          客戶機將實例化 DMS,并調(diào)用 get() 方法訪問特定的雇員:Big Boss、Wayne Blanchard 和 Terence Shorter。它以用戶友好的方式在控制臺中打印這些雇員的信息,然后更新 Terence Shorter 及其雇員的部門信息。最后調(diào)用 DMS 的 update() 方法,傳遞更新的 Terence Shorter 數(shù)據(jù)圖。

          注意,為了便于示范,我們沒有實現(xiàn)數(shù)據(jù)源組件,但在 DMS 中,有一些如何根據(jù)查詢構(gòu)建數(shù)據(jù)圖的“硬編碼”知識。圖 3 顯示了 DMS 正在使用的雇員層次結(jié)構(gòu)。

          圖 3. Big Boss 公司的雇員
          Big Boss 公司的雇員

          圖中可以看出,DMS 背后的虛擬公司有 4 個雇員,層次結(jié)構(gòu)如下:

          • Big Boss 沒有上司,Terence Shorter 是其下屬。
          • Terence Shorter 以 Big Boss 作為自己的上司,John Datrane 和 Miles Colvis 是其下屬。
          • John Datrane 的上司是 Terence Shorter,沒有下屬。
          • Miles Colvis 的上司是 Terence Shorter,沒有下屬。

          運行示例應(yīng)用程序
          右擊 SDOClient.java,然后選擇 Run>Java application運行上述示例應(yīng)用程序,結(jié)果如下:

          清單 2. 應(yīng)用程序的控制臺輸出
          
          ********* EMPLOYEE INFORMATION *********
          
          Name: John Datrane
          Number: 4
          Title: Mr.
          Department: Procurement
          Is manager?: no
          
          DIRECT MANAGER:
          
          Name: Terence Shorter
          Number: 2
          Title: Mr.
          Department: Financing
          Is manager?: yes
          
          ****************************************
          
          NO INFORMATION AVAILABLE ON EMPLOYEE Wayne Blanchard
          
          ********* EMPLOYEE INFORMATION *********
          
          Name: Terence Shorter
          Number: 2
          Title: Mr.
          Department: Financing
          Is manager?: yes
          
          DIRECT MANAGER:
          
          Name: The Big Boss
          Number: 1
          Title: Mr.
          Department: Board
          Is manager?: yes
          
          DIRECT EMPLOYEES:
          
          Name: Miles Colvis
          Number: 3
          Title: Mr.
          Department: Accounting
          Is manager?: no
          
          Name: John Datrane
          Number: 4
          Title: Mr.
          Department: Procurement
          Is manager?: no
          
          [Total: 2]
          ****************************************
          
          DMS updating Terence Shorter
           (changed department from "Financing" to "The new department")
          DMS updating Miles Colvis
           (changed department from "Accounting" to "The new department")
          DMS updating John Datrane
           (changed department from "Procurement" to "The new department")
          

          現(xiàn)在我們來分析應(yīng)用程序的各個組成部分是如何工作的。

          客戶機
          SDO 客戶機例示了 DMS,并從中獲得不同雇員的數(shù)據(jù)圖。得到數(shù)據(jù)圖后,通過根對象(使用 SDO 動態(tài) API)遍歷和訪問數(shù)據(jù)對象,如下所示:

          
          // Get the SDO DataGraph from the DMS.
          DataGraph employeeGraph = mediator.get(employeeName);
          ...
          // Get the root object
          DataObject root = employeeGraph.getRootObject();
          ...
          // get the employee under the manager
          employee = theManager.getDataObject("employees.0");
          

          客戶機調(diào)用動態(tài) SDO 訪問器 API,從數(shù)據(jù)對象中獲得信息,并將其顯示到控制臺上:

          
          System.out.println("Name: " + employee.getString("name"));
          System.out.println ("Number: " + employee.getInt("number"));
          ...
          System.out.println ("Is manager?: " + 
            (employee.getBoolean("manager") ? "yes" : "no") + "\n");
          

          我們已經(jīng)看到客戶機是如何獲取信息(讀)的,但是如何寫入信息呢?更準(zhǔn)確地說,客戶機如何修改對象?SDO 客戶機一般使用 DataObject 寫訪問器方法更新數(shù)據(jù)對象。比如,下面的代碼修改從雇員 Terence Shorter 獲得的數(shù)據(jù)圖:

          
          employee.setString("department", newDepartmentName);
          

          注意,客戶機沒有調(diào)用日志方法。DMS 負(fù)責(zé)對數(shù)據(jù)圖的變更摘要調(diào)用 beginLogging()endLogging() 記錄日志。

          數(shù)據(jù)圖
          可以將數(shù)據(jù)圖的數(shù)據(jù)格式(模型)看作 DMS 與客戶機之間的抽象??蛻魴C期望從 DMS 得到數(shù)據(jù)圖,DMS 也知道如何創(chuàng)建數(shù)據(jù)讀(包括從后端數(shù)據(jù)源中讀取和更新數(shù)據(jù))。如果熟悉 XML 或者 Web 服務(wù),那么可以將數(shù)據(jù)圖模型看作定義數(shù)據(jù)對象 XML Schema(XSD)。數(shù)據(jù)圖本身就類似 XML 實例文檔。事實上,XML Schema 也是定義 SDO 模型的一種方法。

          注意,數(shù)據(jù)圖及其模型總是能夠序列化為 XML。在 SDOClient.java 中將 debug 變量設(shè)為 true ,就可以看到運行時在控制臺中顯示的數(shù)據(jù)圖的序列化版本,與清單 3 類似。

          清單 3. 數(shù)據(jù)圖的序列化版本
          
          <?xml version="1.0" encoding="UTF-8"?>
          <sdo:datagraph xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:company="http://com.example.company.ecore"
            xmlns:sdo="commonj.sdo"
            xmlns:sdo_1="http://www.eclipse.org/emf/2003/SDO">
            <changeSummary>
              <objectChanges key="#//@eRootObject">
                <value xsi:type="sdo_1:EChangeSummarySetting"
                  featureName="department" dataValue="Board"/>
              </objectChanges>
            </changeSummary>
            <company:Employee name="The Big Boss"
              number="1" department="The new department" title="Mr."
              manager="true">
              <employees name="Terence Shorter" number="2"
                department="The new department" title="Mr." manager="true">
                <employees name="Miles Colvis" number="3"
                  department="The new department" title="Mr."/>
                <employees name="John Datrane" number="4"
                  department="The new department" title="Mr."/>
              </employees>
            </company:Employee>
          </sdo:datagraph>
          

          在本例中,數(shù)據(jù)圖由 Employee 數(shù)據(jù)對象(以及變更摘要)組成。 Employee 包含姓名、編號、部門、職務(wù)、上司(管理該雇員的另一位雇員)和下屬(該雇員管理的其他雇員)等屬性。該例中,雇員已經(jīng)位于硬編碼的數(shù)據(jù)源中時,DMS 返回的數(shù)據(jù)圖的格式總是雇員的上司(如果有的話)、雇員及其直接下屬(如果有的話)。

          DMS 構(gòu)建數(shù)據(jù)圖
          SDO 1.0 沒有規(guī)定 DMS API,API 應(yīng)該包含數(shù)據(jù)圖模型本身的設(shè)計和創(chuàng)建。因為建立對數(shù)據(jù)源的訪問要考慮很多種情況,設(shè)計數(shù)據(jù)圖本身可以作為另一篇文章的主題。

          對這個例子,我們將采用 DMS 通過動態(tài) EMF API 定義的雇員模型。示例數(shù)據(jù)圖沒有 XSD 這樣的模型文檔。實際上,因為對象是動態(tài)生成的,所以這意味著沒有生成 Employee Java 類。如果使用靜態(tài)方法,就會生成這樣的類。

          DMS 使用不同的數(shù)據(jù)訪問 API(JDBC、SQL 等)從不同數(shù)據(jù)源獲取的信息。但是,一旦從后端(該例中是硬編碼的知識)檢索到信息,DMS 就轉(zhuǎn)而使用 EMF API(eSet、eGet)而非 SDO API 來創(chuàng)建數(shù)據(jù)對象的數(shù)據(jù)圖。這種方法能得到較好的性能,但缺點是不能跨 SDO 實現(xiàn)移植。

          對于主要關(guān)注性能,同樣的 DMS 設(shè)計也可使用 SDO API 實現(xiàn)。在這種情況下,DMS 類( employeeClassemployeeNameFeature 等)中緩沖的元對象,將代替 EMF 類型 EClassEAttributeEReference 等),成為 commonj.sdo.Typecommonj.sdo.Property 的類型。此外,如果性能不重要,那么可以方便地使用基于 String 的 SDO API(如 setBoolean(String path, boolean value) ),因此不需要緩沖元對象。不幸的是,這種解決方案雖然更方便,但運行起來也更慢。

          下面的代碼片段說明了 SimpleEmployeeDataMediatorImpl.java 中 Employee 模型的定義。但這些代碼并沒有構(gòu)建 SDO 對象,構(gòu)建的僅僅是 SDO 對象的模型:

          
          protected EClass employeeClass;
          protected EAttribute employeeNameFeature;
          protected EReference employeeEmployeesFeature;
          ...
          
          employeeClass = ecoreFactory.createEClass();
          employeeClass.setName("Employee");
          
          EAttribute employeeNameFeature = ecoreFactory.createEAttribute();
          ...
              
          // employees (that the employee manages)
          employeeEmployeesFeature = ecoreFactory.createEReference();
          employeeEmployeesFeature.setContainment(true);
          ...
          
          EPackage employeePackage = ecoreFactory.createEPackage();
          employeePackage.getEClassifiers().add(employeeClass);
          ...
          

          注意,我們使用值 trueemployees EReference 調(diào)用 setContainment ,因此每個雇員都“包含”他或她的下屬。否則,嵌套的雇員就不會(即被包含)在數(shù)據(jù)圖中,變更摘要也只能包含根對象的修改,而不能包含其他雇員的修改。

          建模 SDO
          您可能想“很有趣,但是這樣只能得到 EMF 對象而不是 SDO 對象,還有什么竅門嗎?”當(dāng)然有,而且很簡單。 Employee EClass 屬于 employeePackage EPackage ,并且包含下面的調(diào)用:

          
          // Have the factory for this package build SDO Objects
          employeePackage.setEFactoryInstance(
            new DynamicEDataObjectImpl.FactoryImpl());
          

          運行時,這個工廠將創(chuàng)建 DynamicEDataObjectImpl 類型的對象,該對象實現(xiàn)了 DataObject 接口(即它是一個 SDO 數(shù)據(jù)對象),而不是默認(rèn)的 DynamicEObjectImpl 接口,并且可以智能地創(chuàng)建普通的 EMF 對象。SDO 和 EMF 對象之間的關(guān)系就很清楚了:SDO 對象就是同時實現(xiàn)了 SDO DataObject 接口的 EMF 對象。事實上,這些附加方法的實現(xiàn)是委派給核心 EMF 方法實現(xiàn)的。

          創(chuàng)建 SDO 實例
          現(xiàn)在,已經(jīng)擁有了我們的數(shù)據(jù)對象,就可以建立 Employee 的實例并設(shè)置不同的屬性了。如前所述,我們將使用 EMF API 來最大程度地提高性能。

          
          EObject eObject = EcoreUtil.create(employeeClass);
          
          // Note: we could cast the object to DataObject,
          // but chose to use EObject APIs instead.
          eObject.eSet(employeeNameFeature, name);
          eObject.eSet(employeeNumberFeature, new Integer(number));
          ... ...
          

          可以使用“employees”引用把雇員“鏈接”在一起,比如:

          
          ((List)bigBoss.eGet(employeeEmployeesFeature)).add(terence);
          

          一旦創(chuàng)建了數(shù)據(jù)對象,還需要將其連接到數(shù)據(jù)圖中。我們首先要調(diào)用數(shù)據(jù)圖的 setRootObject() 方法,傳遞希望用作根的數(shù)據(jù)對象,這里使用 Employee The Boss

          
          EDataGraph employeeGraph = SDOFactory.eINSTANCE.createEDataGraph();
          ... ...
          employeeGraph.setERootObject(rootObject);
          

          繼續(xù)討論數(shù)據(jù)圖之前,要先開始記錄日志。如果希望使用 SDO,那么在改動數(shù)據(jù)圖之前,要先調(diào)用其變更摘要的 beginLogging() 方法。基本的原理就是清除以前的變化,開始監(jiān)聽新的修改。

          
          // Call beginLogging() so that the Change Summary is
          // populated when changes are applied to the Data Graph.
          // The DMS should call beginLogging() and endLogging(),
          // not the client.
          employeeGraph.getChangeSummary().beginLogging();
          

          DMS 的另一項任務(wù)(按照 EmployeeDataMediator 接口的定義)是根據(jù) SDO 客戶機提供的數(shù)據(jù)圖更新后端數(shù)據(jù)源。

          DMS:更新數(shù)據(jù)源
          DMS 應(yīng)該使用 SDO 的強大特性更新后端數(shù)據(jù)源,具體地說,就是要使用其變更摘要。使用數(shù)據(jù)圖的變更摘要有許多不同的方法。該例中,我們將考察變更摘要樹中引用的所有數(shù)據(jù)對象,并從中獲得新的數(shù)據(jù)對象。

          清單 4. DMS 根據(jù)數(shù)據(jù)圖更新后端數(shù)據(jù)源
          
          /**
           * Update the DMS's backend data to reflect changes
           * in the data graph.
           * Since this DMS has no actual backend data and therefore
           * has nothing to update, we will just navigate
           * the change summary and report (print) what's changed.
           */
          public void update(DataGraph dataGraph)
          {
            ChangeSummary changeSummary = dataGraph.getChangeSummary();
           
            // Call endLogging to summarize changes.
            // The DMS should call beginLogging() and endLogging(),
            // not the client.
            changeSummary.endLogging();
           
            // Use SDO ChangeSummary's getChangedDataObjects() method.
            List changes = changeSummary.getChangedDataObjects();
            for (Iterator iter = changes.iterator(); iter.hasNext();)
            {
              DataObject changedObject = (DataObject)iter.next();
              System.out.print("DMS updating " +
                changedObject.getString("name"));
          
              for (Iterator settingIter = changeSummary.getOldValues(
                changedObject).iterator(); settingIter.hasNext();)
              {
                ChangeSummary.Setting changeSetting =
                  (ChangeSummary.Setting)settingIter.next();
                Property changedProperty = changeSetting.getProperty();
                Object oldValue = changeSetting.getValue();
                Object newValue = changedObject.get(changedProperty);
          
                System.out.print(" (changed: " + changedProperty.getName() +
                  " from \"" + oldValue + "\" to \"" + newValue + "\")");
                // If not a simple example, we could update the backend here.
              }
          
              System.out.println();
            }
          }
          

          該例中根本沒有后端更新。但在實際應(yīng)用時,后端更新應(yīng)該在這個方法中完成。

          DMS 首先要對數(shù)據(jù)圖的更新摘要調(diào)用 endLogging() ,從客戶機取回數(shù)據(jù)圖,以便進行后端更新。這樣將關(guān)閉變更記錄,從而提供自 beginLogging() 調(diào)用以來(通常在創(chuàng)建之后調(diào)用)對數(shù)據(jù)圖所做修改的摘要。這種格式支持 DMS 高效、遞增地更新后端數(shù)據(jù)源。變更摘要中的修改分為三種類型:

          • 對象變更包含數(shù)據(jù)圖中屬性已經(jīng)被修改的那些數(shù)據(jù)對象的引用、被修改的屬性和修改之前的屬性值。DMS 可以使用原來的屬性值確保后端數(shù)據(jù)在此期間沒有被別的人修改。

          • 對象創(chuàng)建包含添加到數(shù)據(jù)圖中的數(shù)據(jù)對象。將這些對象表示了需要添加到后端數(shù)據(jù)結(jié)構(gòu)中的新數(shù)據(jù)。

          • 對象刪除包含從數(shù)據(jù)圖中刪除的數(shù)據(jù)對象。這些對象表示了需要從后端數(shù)據(jù)結(jié)構(gòu)中刪除的數(shù)據(jù)。

          注意,我們使用標(biāo)準(zhǔn)的 SDO API 檢查數(shù)據(jù)圖的變化,雖然也可以使用 EMF ChangeDescription API(而不是 SDO 的 ChangeSummary)。該例中僅僅更新簡單的屬性值,對性能的影響不是很明顯。但在其他情況下,比方說要更新大量的屬性,使用 EMF API 可以顯著地提高性能。比如,假設(shè)要從數(shù)百個雇員的列表中刪除一個雇員。在這種情況下,ChangeSummary 只能提供對原有數(shù)百個雇員列表中的原有值的訪問。 而 EMF 的 ChangeDescription 接口還可以提供更具體的信息,如“刪除某個索引位置的雇員”,這就有用得多。

          還要注意的是,該變更摘要中只修改了一個對象,沒有刪除或者添加對象。如果使用 SDO 實現(xiàn)從數(shù)據(jù)圖中刪除對象,還要注意類型為 objectsToAttach 的元素。該名稱實際上是對象刪除的 EMF ChangeDescription 名。這些元素是那些已經(jīng)刪除但是在回滾時需要放回圖中的數(shù)據(jù)對象,這就是變更的 EMF 視圖。總而言之, objectsToAttach == deleted objects(刪除的對象)

          調(diào)試應(yīng)用程序
          如果在示例應(yīng)用程序中將 debug 變量設(shè)為 true ,那么就可以執(zhí)行以下調(diào)用,查看數(shù)據(jù)圖的序列化版本。

          
          ((EDataGraph) dataGraph).getDataGraphResource().save(System.out, null);
          

          還可以使用 Eclipse 調(diào)試環(huán)境。比如,我們建議在 SDOClient.java 第 100 行設(shè)置一個斷點,并調(diào)試 SDOClient (像在 Java 應(yīng)用程序中那樣)。然后,在調(diào)試窗口中就可以看到內(nèi)存中的數(shù)據(jù)圖(在 Variables 下)和它的數(shù)據(jù)對象(Boss、Terrence Shorter 等),如圖 4 所示。

          圖 4. 在調(diào)試模式下觀察數(shù)據(jù)對象
          調(diào)試

          還可以用這種方法查看變更摘要,如圖 5 所示。

          圖 5. 在調(diào)試模式下觀察變更摘要
          調(diào)試

          上面的截屏圖看起來很復(fù)雜,現(xiàn)在看來用處也不大,但是當(dāng)您調(diào)試自己的 SDO 應(yīng)用程序并查看數(shù)據(jù)對象和變更摘要的內(nèi)容時,就會用到它。

          結(jié)束語
          本文簡要描述了 SDO 及其功能。我們通過一個示例應(yīng)用程序說明了 SDO 的一些功能。更多參考信息,請參閱 Eclipse 幫助系統(tǒng)下的 SDO API 文檔。該規(guī)范仍在發(fā)展和改進之中。比如,SDO 1.0 強調(diào)了 SDO 的客戶機方面,而沒有指定一個 DMS API。SDO 目前正通過 JCP 實現(xiàn)標(biāo)準(zhǔn)化,請關(guān)注有關(guān)的進展情況。因為 SDO 非常靈活,設(shè)計 SDO 應(yīng)用程序時需要做很多決策。這些決策將影響程序的重用性和性能。因此,在編碼之前,應(yīng)該認(rèn)真考慮應(yīng)用模式和應(yīng)用程序數(shù)據(jù)的特征。

          參考資料

          下載
          Name Size Download method
          j-sdoSample.zip FTP
          *關(guān)于下載方法的信息
          作者簡介
          Bertrand Portier 是 IBM 的軟件開發(fā)人員,他是在 Eclipse.org 上開發(fā) SDO 參考實現(xiàn)的 EMF 開發(fā)小組的主要成員。他擁有使用 J2EE 的豐富經(jīng)驗,曾經(jīng)參與過 IBM 產(chǎn)品和 Web 服務(wù)領(lǐng)域的開發(fā),并幫助 IBM 客戶開發(fā)自己的分布式應(yīng)用程序。


          Frank Budinsky 是 Eclipse.org 的 Eclipse Modeling Framework 項目經(jīng)理,參與了 EMF 框架的架構(gòu)和實現(xiàn),其中包括 SDO 的參考實現(xiàn)。他是 IBM Software Group 的工程師,有多年框架和生成器設(shè)計方面的經(jīng)驗。Frank 是權(quán)威的 EMF 參考書 Eclipse Modeling Framework, A Developer's Guide 的主要作者。



          原文地址:http://www-128.ibm.com/developerworks/cn/java/j-sdo/
          posted on 2005-12-14 16:51 hopeshared 閱讀(1416) 評論(2)  編輯  收藏 所屬分類: Eclipse

          Feedback

          # re: 轉(zhuǎn): 服務(wù)數(shù)據(jù)對象簡介 2006-01-22 22:26 reload_cn
          SDO好是好,只是..... 總感覺怪怪的!  回復(fù)  更多評論
            

          # re: 轉(zhuǎn): 服務(wù)數(shù)據(jù)對象簡介 2006-02-15 09:59 limeiyong
          好文章!!!!!!!!!!!!  回復(fù)  更多評論
            

          主站蜘蛛池模板: 河北区| 丹棱县| 芜湖市| 茶陵县| 文登市| 亳州市| 彰化县| 元氏县| 社旗县| 原平市| 南汇区| 平原县| 喜德县| 鹿泉市| 荃湾区| 扎囊县| 恩平市| 慈溪市| 文安县| 郁南县| 沛县| 四子王旗| 宁陕县| 德兴市| 镇坪县| 垦利县| 吉木萨尔县| 澄城县| 奉贤区| 仪陇县| 栾城县| 陆川县| 盐池县| 明水县| 廉江市| 忻城县| 万山特区| 胶州市| 永兴县| 嘉鱼县| 祁东县|