• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 181, 文章 - 2, 評(píng)論 - 85, 引用 - 0
            數(shù)據(jù)加載中……

            使用 SDO 和 JDBC Data Access Service 啟用SOA

            本文對(duì)隨 IBM? Rational? Application Developer V6 一起提供的數(shù)據(jù)訪問(wèn)服務(wù)(Data Access Services,DAS)進(jìn)行了概述,并對(duì)這些訪問(wèn)服務(wù)在使用服務(wù)數(shù)據(jù)對(duì)象(Service Data Object,SDO)的面向服務(wù)的體系結(jié)構(gòu) (SOA) 中扮演的角色進(jìn)行了說(shuō)明。

            引言

            IBM Rational Application Developer for WebSphere? Software V6 所包含 JDBC Data Access Services 提供了對(duì)面向服務(wù)的體系結(jié)構(gòu)的持久化層的標(biāo)準(zhǔn)化訪問(wèn)。數(shù)據(jù)訪問(wèn)服務(wù) (DAS) 與服務(wù)數(shù)據(jù)對(duì)象 (SDO) 密切相關(guān),因此要了解 DAS 的概念,首先需要了解一下 SDO。

            在本文講述的高級(jí)部分,將給出一個(gè)端到端的示例應(yīng)用程序,該應(yīng)用程序使用適合開(kāi)發(fā)人員和架構(gòu)師使用的 JDBC DAS。該示例使用 XML 對(duì)象關(guān)系映射信息保存對(duì) SDO 對(duì)象圖的更改。(請(qǐng)參閱參考資料,以獲得有關(guān) SDO 的更多信息。)

            什么是 SDO?

            服務(wù)數(shù)據(jù)對(duì)象(Service Data Objects,SDO)是一項(xiàng)新興標(biāo)準(zhǔn),用于表示企業(yè)應(yīng)用程序中的數(shù)據(jù)。SDO 是信息的容器,設(shè)計(jì)用于提升開(kāi)放標(biāo)準(zhǔn)和互操作性。SDO 提供了在整個(gè)企業(yè)應(yīng)用程序中表示信息的方法,包括表示層、業(yè)務(wù)邏輯層和此類層之間的通信,如圖 1 所示。


            圖 1. SDO 概述
            圖 1. SDO 概述

            服務(wù)數(shù)據(jù)對(duì)象的主要特性包括:

            • SDO 可以包含嵌套對(duì)象。此功能稱為對(duì)象圖,是一種非常靈活的表示數(shù)據(jù)的方式。例如,圖 2 中的 SDO 就表示一個(gè)有各種產(chǎn)品的多個(gè)訂單的客戶:


              圖 2. SDO 數(shù)據(jù)圖
              圖 2. SDO 數(shù)據(jù)圖
            • SDO 支持 XPath,可以訪問(wèn)其封裝的數(shù)據(jù)。XML 路徑語(yǔ)言 (XPath) 是一項(xiàng)開(kāi)放標(biāo)準(zhǔn),是由 World Wide Web Consortium (W3C) 制定的,用于從 XML 文檔訪問(wèn)數(shù)據(jù)。例如,可以使用以下字符串訪問(wèn)特定的產(chǎn)品:CustomerOrder/Product[name='MP3Player'],其中,CustomerOrder 為 Customer 和 Order 之間定義的關(guān)系。

            • SDO 可以作為 XML 構(gòu)件或 Java? 對(duì)象存在。借助對(duì) XML 的這項(xiàng)透明支持,直接使用 <datagraph> 標(biāo)記作為開(kāi)頭來(lái)傳遞 XML SDO,就可以通過(guò) Web 服務(wù)(或任何 XML 傳輸,如 REST 或 XML-RPC)傳遞 SDO。而且,僅在 SDO v1 中使用更改摘要時(shí),才有必要使用 <datagraph> 標(biāo)記。在其他所有情況下,可以使用任何標(biāo)記。

            • SDO 包含更改摘要。SDO 更改摘要作為所有活動(dòng)的歷史記錄使用,通過(guò)使用此功能,應(yīng)用程序可以將舊數(shù)據(jù)和新數(shù)據(jù)區(qū)分開(kāi)。例如,加入某個(gè)客戶決定下新訂單。接受訂單的企業(yè)系統(tǒng)由圖 3 中的高級(jí)組件組成。請(qǐng)注意,包含新訂單的 SDO 將從門(mén)戶服務(wù)器傳遞到后端服務(wù)。如果沒(méi)有更改摘要,后端服務(wù)必須將 SDO 中的所有數(shù)據(jù)放入數(shù)據(jù)庫(kù)。不過(guò),由于可以訪問(wèn) SDO 更改摘要,因此,只需要將新數(shù)據(jù)放入數(shù)據(jù)庫(kù)即可,從而提高后端服務(wù)的效率。此外,門(mén)戶服務(wù)器可以通過(guò)使用更改摘要來(lái)傳遞更小的 SDO,該 SDO 中僅包含在前端所做的更改。


              圖 3. 更改摘要
              圖 3. 更改摘要
            • SDO 是開(kāi)放標(biāo)準(zhǔn)。SDO 1.0 和 2.0 規(guī)范均是由 BEA? 和 IBM 聯(lián)合發(fā)布的(請(qǐng)參閱參考資料)。任何組織都可以免費(fèi)使用和實(shí)現(xiàn)這些標(biāo)準(zhǔn)。

            什么是 DAS?

            數(shù)據(jù)訪問(wèn)服務(wù) (Data Access Service) 根據(jù) SDO 1.0 標(biāo)準(zhǔn)保存 SDO。DAS 可以采用任何持久化機(jī)制實(shí)現(xiàn)。例如,Rational Application Developer V6 包括了一個(gè) JDBC DAS 和一個(gè) EJB 實(shí)體 Bean DAS,允許采用標(biāo)準(zhǔn)方式將 SDO 保存到各種后端系統(tǒng),從而提升企業(yè)應(yīng)用程序內(nèi)的互操作性和標(biāo)準(zhǔn)。


            圖 4. DAS 概述
            圖 4. DAS 概述

            DAS 是一項(xiàng)新興的規(guī)范,其標(biāo)準(zhǔn)化進(jìn)程仍在進(jìn)行之中。現(xiàn)在稱為 DAS 的新一輪工作就是即將推出的數(shù)據(jù)訪問(wèn)服務(wù) (DAS) 標(biāo)準(zhǔn)。可以將 DAS 稱為 DAS 2.0。DAS 將對(duì) SDO 2.0 規(guī)范形成補(bǔ)充,正在制定之中(DAS 被認(rèn)為處于 SDO 2.0 規(guī)范之外)。







            面向服務(wù)的體系結(jié)構(gòu)中的數(shù)據(jù)訪問(wèn)服務(wù)

            SDO 數(shù)據(jù)訪問(wèn)服務(wù)非常適合作為 SOA 服務(wù)公開(kāi)。他們提供了一個(gè)標(biāo)準(zhǔn),用于構(gòu)建可以在 SOA 服務(wù)間共享的后端服務(wù)。例如,假如有一個(gè)必須和兩個(gè)不同業(yè)務(wù)進(jìn)行通信的企業(yè)系統(tǒng)。這兩個(gè)業(yè)務(wù)服務(wù)使用完全不同的技術(shù)保存信息。如果傳遞給這些服務(wù)的消息為 SDO,則兩個(gè)服務(wù)都可以使用 DAS,企業(yè)應(yīng)用程序可以將其看作同一個(gè)組織而進(jìn)行處理,如圖 5 中所示。


            圖 5. SOA 中的 SDO 數(shù)據(jù)訪問(wèn)服務(wù)
            圖 5. SOA 中的 SDO 數(shù)據(jù)訪問(wèn)服務(wù)

            DAS 還可以提高 SOA 的可維護(hù)性。實(shí)現(xiàn) SOA 的一個(gè)常見(jiàn)毛病就是會(huì)假設(shè)公開(kāi)服務(wù)總是有好處的。當(dāng)公開(kāi)了服務(wù)時(shí),要更改非常困難——對(duì)于那些向客戶或公眾公開(kāi)某種功能的服務(wù)更是如此。例如,假設(shè)某家銀行有一項(xiàng)已公開(kāi)了數(shù)年的服務(wù),由于政府法規(guī)的原因,現(xiàn)在必須對(duì)其進(jìn)行更改——在網(wǎng)上傳輸?shù)南⒈仨毥?jīng)過(guò)加密,如圖 6 中所示。


            圖 6. SOA 中的 DAS 和可維護(hù)性
            圖 6. SOA 中的 DAS 和可維護(hù)性

            如果有數(shù)百合作伙伴訪問(wèn)該服務(wù),該銀行不會(huì)輕易更改服務(wù),因?yàn)槠浜献骰锇閷⒉辉倌芘c他們開(kāi)展業(yè)務(wù)。該銀行的最佳選擇可能就是構(gòu)建另一個(gè) 99% 冗余的服務(wù),并盡力說(shuō)服其合作伙伴轉(zhuǎn)而使用新服務(wù)。這將使用大量資源,而所得到的業(yè)務(wù)價(jià)值也有限。

            將 SDO 和 DAS 配合使用,可以減緩這類問(wèn)題,因?yàn)?SDO 是動(dòng)態(tài)性非常強(qiáng)的消息。如果該銀行使用的是 SDO,則可以直接通知其合作伙伴對(duì)添加的信息進(jìn)行加密,而不會(huì)更改已公開(kāi)的服務(wù)——只需要更改傳遞給該服務(wù)的消息。如果某個(gè)合作伙伴仍然發(fā)送舊 SDO XML 格式的消息,通過(guò)檢查 SDO 的內(nèi)容(并可能與不兼容的業(yè)務(wù)合作伙伴聯(lián)系),銀行的應(yīng)用程序?qū)⒛軌驅(qū)Υ祟惽闆r作出判斷,然后按照以前的方式處理此類信息。







            使用 SDO 數(shù)據(jù)訪問(wèn)服務(wù)的業(yè)務(wù)案例

            在現(xiàn)有持久化技術(shù)的基礎(chǔ)上將 SDO 和 DAS 結(jié)合使用,除了 SOA 的好處之外,其業(yè)務(wù)價(jià)值何在呢?請(qǐng)考慮以下管理方面的特征:

            • SDO 是一項(xiàng)開(kāi)放標(biāo)準(zhǔn)。由于 SDO 是一項(xiàng)公開(kāi)的標(biāo)準(zhǔn),因此不會(huì)出現(xiàn)不得不選用某個(gè)供應(yīng)商的情況。截至本文發(fā)布時(shí),BEA、IBM、Versant、Versata 和 XCalia 均推出了 SDO 實(shí)現(xiàn)。同樣,也已計(jì)劃對(duì) SDO 的數(shù)據(jù)訪問(wèn)進(jìn)行標(biāo)準(zhǔn)化。

            • SDO 和 DAS 可以減少業(yè)務(wù)所必須維護(hù)的代碼量。數(shù)據(jù)訪問(wèn)服務(wù)提供了一種標(biāo)準(zhǔn)的方法,用于保存封裝在 SDO 中的信息,而不受后端系統(tǒng)的影響(不管此后端系統(tǒng)是使用 JDBC 訪問(wèn)的關(guān)系數(shù)據(jù)庫(kù)、使用視圖 Bean 訪問(wèn)的 LDAP 服務(wù)器或是具有 DAS 實(shí)現(xiàn)的其他后端系統(tǒng))。實(shí)際上,為了使用異構(gòu)后端系統(tǒng)而編寫(xiě)的自定義代碼與數(shù)據(jù)訪問(wèn)服務(wù)采用標(biāo)準(zhǔn)的方式進(jìn)行了整合。需要維護(hù)的代碼較少,通常可以盡可能減少潛在的缺陷,從而縮短投入市場(chǎng)的時(shí)間和減少風(fēng)險(xiǎn)。

            • 將 SDO 和 DAS 結(jié)合使用,不需要受具體的持久化技術(shù)限制。DAS 不僅使應(yīng)用程序無(wú)需依賴于數(shù)據(jù)庫(kù)或操作系統(tǒng),而且還使應(yīng)用程序獨(dú)立于整個(gè)持久化技術(shù)。通過(guò)使用多個(gè)數(shù)據(jù)訪問(wèn)服務(wù),應(yīng)用程序可以支持這些中介的基礎(chǔ)持久化機(jī)制,而不用更改業(yè)務(wù)邏輯或呈現(xiàn)邏輯。對(duì)于 IT 環(huán)境復(fù)雜的組織,這樣可以減少成本、整合資產(chǎn),并可以減少將來(lái)進(jìn)行高成本技術(shù)更改的風(fēng)險(xiǎn)。

            • 使用 SDO 和 DAS 有得有失。這兩項(xiàng)均是新興技術(shù),尚處于早期發(fā)布階段。很多數(shù)據(jù)訪問(wèn)服務(wù)可能不支持其他持久化技術(shù)的最先進(jìn)功能(除非 DAS 專門(mén)為支持該技術(shù)而構(gòu)建)。例如,IBM 的 JDBC Data Access Service 就尚不支持 SDO 表群集環(huán)境的分布式緩存。另外,若要充分發(fā)揮 SDO 和 DAS 的潛力,可能需要對(duì)各種新技術(shù)有所了解,包括 Web 服務(wù)、XPath 及 SDO 規(guī)范。對(duì)于開(kāi)發(fā)組織,可以需要進(jìn)行培訓(xùn)。







            按部就班,使用 JDBC Data Access Service

            本文剩下的部分將給出一個(gè)實(shí)例應(yīng)用程序的實(shí)現(xiàn)。就功能而言,CloseOrderApplication 將使用 Rational Application Developer V6 包含的 JDBC DAS 關(guān)閉客戶的訂單。該應(yīng)用程序?qū)臄?shù)據(jù)庫(kù)檢索一個(gè) SDO 對(duì)象圖,對(duì)其進(jìn)行更小,然后保存更改。將數(shù)據(jù)庫(kù)架構(gòu)映射到 SDO 對(duì)象圖的元數(shù)據(jù)是使用 XML 編寫(xiě)的。

            JDBC DAS 編程模型

            圖 7 所示的關(guān)系圖演示了使用 JDBC Data Access Service 開(kāi)發(fā)應(yīng)用程序時(shí)應(yīng)該有用的編程模型。


            圖 7. JDBC DAS 編程模型
            圖 7. JDBC DAS 編程模型
            關(guān)于示例應(yīng)用程序
            此示例不僅是試驗(yàn)性的代碼,因?yàn)槠渲袑?shí)現(xiàn)了 JavaEE 最佳實(shí)踐和實(shí)際錯(cuò)誤處理。如果確實(shí)需要利用 JDBC Data Access Service 的代碼(通常不過(guò)寥寥幾行而已),清單 1 和清單 6 無(wú)疑是最為相關(guān)的了。數(shù)據(jù)庫(kù)設(shè)置、JavaEE 數(shù)據(jù)源定義、XML 元數(shù)據(jù)的 JNDI 查詢以及異常處理均屬于 JavaEE 開(kāi)發(fā)期間要做的工作,而不屬于 SDO JDBC DAS。

            在此模型中,JDBC DAS 使用 ConnectionWrapper 對(duì) JDBC Connection 加以包裝,以連接到數(shù)據(jù)存儲(chǔ)區(qū)。使用 MetadataFactory 創(chuàng)建了 Metadata 的實(shí)例。然后使用各種構(gòu)造(如 Tables、Columns 及 Relationships)定義元數(shù)據(jù)。數(shù)據(jù)庫(kù)查詢的等效項(xiàng)在元數(shù)據(jù)中定義為篩選器。不過(guò),在此示例中,元數(shù)據(jù)、表、列、關(guān)系和篩選器均在元數(shù)據(jù)中定義,且在 XML 映射文檔需要時(shí)透明地創(chuàng)建。(請(qǐng)參閱參考資料,以了解如何如上所示,在運(yùn)行時(shí)使用元數(shù)據(jù) API。)定義了元數(shù)據(jù)后,就會(huì)將其與 ConnectionWrapper 一起使用,以創(chuàng)建 JDBCAccess。中介可以獲取和保存 SDO DataObject 圖。

            我們將通過(guò)執(zhí)行以下任務(wù)來(lái)實(shí)現(xiàn)此實(shí)例應(yīng)用程序:

            1. 創(chuàng)建 JaveEE 項(xiàng)目
            2. 設(shè)置數(shù)據(jù)庫(kù)
            3. 定義 XML 元數(shù)據(jù)
            4. 創(chuàng)建方法
            5. 創(chuàng)建 JDBC 連接包裝類
            6. 創(chuàng)建 JDBC 中介
            7. 從數(shù)據(jù)庫(kù)檢索 SDO DataObject 圖
            8. 保存 SDO 圖
            9. 關(guān)閉連接
            10. 檢查應(yīng)用程序異常
            11. 使用 Servlet 測(cè)試應(yīng)用程序

            示例應(yīng)用程序的先決條件

            • IBM Rational Application Developer for WebSphere Software V6.0 或更高版本。此外,為了運(yùn)行此示例,需要 IBM WebSphere Application Server 的集成測(cè)試環(huán)境。可以下載 Rational Application Developer 的 30 天免費(fèi)試用版。

            • IBM DB2 UDB V8.0 或更高版本。盡管可以使用任何兼容 JDBC 2.0 的數(shù)據(jù)庫(kù),但此示例將使用 DB2 命令行處理程序設(shè)置數(shù)據(jù)庫(kù),并在 WebSphere Application Server 中將 DB2 配置為數(shù)據(jù)源。可以下載 DB2 的 30 天試用版。

            此示例假設(shè)為 SDO DAS 使用 JavaEE 環(huán)境。不過(guò)并不需要應(yīng)用程序服務(wù)器。IBM JDBC DAS 可以用于任何支持 Java SE 1.3 或更高版本的應(yīng)用程序中。

            1. 創(chuàng)建 JavaEE 項(xiàng)目

            在 Rational Application Developer 的 J2EE Perspective 中:

            1. 選擇 File => New => Enterprise Application Project。將其命名為 CloseOrder,然后選擇 Finish

            2. 右鍵單擊 CloseOrder,選擇 New => Dynamic Web Project,將其命名為 CloseOrderWeb,然后單擊 Finish

            2. 設(shè)置數(shù)據(jù)庫(kù)

            圖 8 顯示了示例應(yīng)用程序的數(shù)據(jù)庫(kù)架構(gòu)。其中包含一個(gè) customer 條目和一個(gè)指向 order 條目的外鍵:


            圖 8. 數(shù)據(jù)庫(kù)架構(gòu)
            圖 8. 數(shù)據(jù)庫(kù)架構(gòu)

            請(qǐng)注意,此處假設(shè)管理用戶名和密碼均為 db2admin

            1. 啟動(dòng) DB2 命令行處理程序。缺省情況下,可以采用以下方式啟動(dòng)此工具:

              • Linux? 或 UNIX?:
                • 作為數(shù)據(jù)庫(kù)管理員登錄(比如 su db2admin
                • 鍵入 db2 并按 Enter
              • Windows?:
                • 選擇 Start => All Programs => IBM DB2 => Command Line Tools => Command Line Processor
            2. 使用命令行處理程序執(zhí)行以下代碼:


              清單 1. DB2 命令
              																
              																								
              db2 => CREATE DATABASE EXAMPLE
              db2 => CONNECT TO EXAMPLE USER db2admin USING db2admin
              db2 => CREATE TABLE CUSTOMER(CUST_ID INTEGER NOT NULL, NAME VARCHAR(250), ORDER_ID INTEGER)
              db2 => ALTER TABLE CUSTOMER PRIMARY KEY(CUST_ID)
              db2 => CREATE TABLE ORDER(ORDER_ID INTEGER NOT NULL, STATUS VARCHAR(250), TOTAL INTEGER, CUSTOMER_ID INTEGER)
              db2 => ALTER TABLE ORDER PRIMARY KEY(ORDER_ID)
              db2 => INSERT INTO CUSTOMER(NAME, CUST_ID, ORDER_ID) VALUES ('Roland Barcia', 1, 2)
              db2 => INSERT INTO CUSTOMER(NAME, CUST_ID, ORDER_ID) VALUES ('Geoffrey Hambrick', 2, 1)
              db2 => INSERT INTO ORDER(ORDER_ID, STATUS, TOTAL, CUSTOMER_ID) VALUES (1, 'OPEN', 88, 1)
              db2 => INSERT INTO ORDER(ORDER_ID, STATUS, TOTAL, CUSTOMER_ID) VALUES (2, 'OPEN', 188, 5)
              db2 => ALTER TABLE CUSTOMER FOREIGN KEY(ORDER_ID) REFERENCES ORDER(ORDER_ID)
              
              																
              														

            3. CloseOrder 示例應(yīng)用程序?qū)?JDBC 數(shù)據(jù)庫(kù)使用 JNDI 上下文引用,以避免硬編碼數(shù)據(jù)庫(kù)連接信息。展開(kāi) CloseOrderWeb,并雙擊 Deployment Descriptor: CloseOrderWeb

            4. 選擇 Reference 選項(xiàng)卡,選擇 Add... => Resourse reference,然后輸入或選擇字段值,如圖 9 中所示。


              圖 9. 數(shù)據(jù)源 JNDI 上下文引用
              圖 9. 數(shù)據(jù)源 JNDI 上下文引用
            5. JNDI name 字段輸入 jdbc/db2/Example,如圖 10 中所示。


              圖 10. 數(shù)據(jù)庫(kù) JNDI 名稱
              圖 10. 數(shù)據(jù)庫(kù) JNDI 名稱

            3. 定義 XML 元數(shù)據(jù)

            若要將數(shù)據(jù)架構(gòu)映射到 SDO 數(shù)據(jù)圖,則必須定義中介元數(shù)據(jù)。


            圖 11. O/R 映射
            圖 11. O/R 映射

            可以在運(yùn)行時(shí)使用 com.ibm.websphere.sdo.mediator.jdbc.metadata.Metadata 定義元數(shù)據(jù),圖 7 對(duì)此作了簡(jiǎn)單描述(請(qǐng)參閱參考資料,以獲得關(guān)于在運(yùn)行時(shí)定義元數(shù)據(jù)的文檔)。不過(guò),我們的示例在 XML 中定義元數(shù)據(jù)。示例應(yīng)用程序?qū)⒃獢?shù)據(jù) XML 文件添加到類路徑中,從而簡(jiǎn)化打開(kāi)指向該文件的 java.io.InputStream 的過(guò)程,如要求創(chuàng)建中介時(shí)。

            1. 在 Rational Application Developer 中,右鍵單擊 CloseOrderWeb 項(xiàng)目,然后選擇 New => Source Folder

            2. 輸入 xml 作為文件夾名稱,然后選擇 Finish

            3. 右鍵單擊 CloseOrderWeb,然后選擇 Java Resources => metadata,再選擇 New => other... => Simple => Folder => Next

            4. 將文件夾命名為 DAS 并選擇 Finish

            5. 右鍵單擊 DAS 文件夾,然后采用類似的方式創(chuàng)建一個(gè)名為 metadata.xml 的新文件。

            6. 插入以下語(yǔ)句作為其內(nèi)容:


              清單 2. 將元數(shù)據(jù)添加到 XML
              																
              																								
              <?xml version="1.0" encoding="ASCII" ?>
              <Metadata rootTable="CUSTOMER" xmlns:="http:///com/ibm/websphere/wdo/mediator/rdb/metadata.ecore" >
              	
              	<tables name="CUSTOMER">
              		<columns name="CUST_ID" type="int" />
              		<columns name="NAME" type="string" />
              		<columns name="ORDER_ID" type="int" />
              		<primaryKey columns="CUST_ID" />
              		<foreignKeys columns="ORDER_ID" />
              		<queryInfo filter="( CUST_ID = ? )">
              			<filterArguments name="CUST_ID" type="int" />
              		</queryInfo>
              	</tables>
              
              	<orderBys column="CUSTOMER.NAME" /> 
              	
              	<tables name="ORDER">
              		<columns name="ORDER_ID" type="int" />
              		<columns name="STATUS" type="string" />
              		<columns name="TOTAL" type="int" />
              		<primaryKey columns="ORDER_ID" />
              	</tables>
              	
              	<relationships name="OWNER" oppositeName="ORDER_RELATION" childKey="CUSTOMER" 
              		parentKey="ORDER" exclusive="false" />
              
              </Metadata>
              																
              														

              列和主鍵的 O/R 映射應(yīng)當(dāng)較為直觀。請(qǐng)考慮以下對(duì)某些其他元數(shù)據(jù)標(biāo)記的描述:

              • <tables rootTable="CUSTOMER">
                SDO 數(shù)據(jù)對(duì)象圖必須定義訪問(wèn)的根入口點(diǎn)。在此應(yīng)用程序中 customer 就是根對(duì)象。

              • <queryInfo>
                此標(biāo)記定義篩選器。如果未定義篩選器,元數(shù)據(jù)將仍然有效;此時(shí)中介會(huì)將所有的客戶(以及所有相關(guān)訂單)作為 SDO 數(shù)據(jù)對(duì)象圖返回。此處定義的篩選器將 SDO 圖的返回縮小,使其僅包含與 filterArgument 匹配的客戶。當(dāng)中介從數(shù)據(jù)庫(kù)檢索此 SDO 圖時(shí),將要求傳入一個(gè)名為 CUST_ID 的 int 類型參數(shù)。請(qǐng)注意,該參數(shù)并沒(méi)有設(shè)置 name = "CUST_ID",因?yàn)槠淇赡芘c數(shù)據(jù)庫(kù)列名稱不同。

              • <relationships>
                此標(biāo)記定義 CUSTOMER.OPEN_ORDER_ID 的外鍵關(guān)系。在此關(guān)系中,customer 是子項(xiàng),而 order 為父項(xiàng)。"Exclusive" 設(shè)置為 false,以指示中介檢索所有相關(guān)訂單,甚至包括沒(méi)有 customer 引用的 order。如果將其設(shè)置為 true,則僅檢索至少有一個(gè)子 customer 引用的 order 項(xiàng)。

              (如果收到驗(yàn)證錯(cuò)誤“Element or attribute do not match QName”,可以將其忽略。本文是入門(mén)級(jí)的文章,將不在 Rational Application Developer 內(nèi)設(shè)置驗(yàn)證。)

            7. 示例應(yīng)用程序使用 JNDI 上下文引用查詢?cè)獢?shù)據(jù)文件的位置。這樣,應(yīng)用程序就可以避免對(duì)文件名稱進(jìn)行硬編碼了。展開(kāi) CloseOrderWeb,然后雙擊 Deployment Descriptor: CloseOrderWeb

            8. 選擇 Reference 選項(xiàng)卡,然后選擇 Add... => Resourse reference,并按照?qǐng)D 12 所示填寫(xiě)值。


              圖 12. 元數(shù)據(jù)資源環(huán)境引用
              圖 12. 元數(shù)據(jù)資源環(huán)境引用
            9. 在 JNDI name 字段中輸入 cell/persistent/string/CloseOrderMetadata,如圖 13 所示。


              圖 13. 元數(shù)據(jù) JNDI 名稱
              圖 13. 元數(shù)據(jù) JNDI 名稱

            4. 創(chuàng)建方法

            現(xiàn)在已經(jīng)準(zhǔn)備好,可以開(kāi)始開(kāi)發(fā)應(yīng)用程序的代碼了。

            1. 右鍵單擊 CloseOrderWeb 項(xiàng)目,并選擇 New => Class

            2. 在 package 中輸入 developerworks.sdo.example 并將其命名為 CloseOrderApplication

            為了更好地描述該應(yīng)用程序,將在接下來(lái)的每一步對(duì) CloseOrderApplication 類的各個(gè)方法單獨(dú)進(jìn)行討論。首先是該類的唯一公共方法 closeOrder(),該方法負(fù)責(zé)整個(gè)示例應(yīng)用程序的組織(圖 14)。


            圖 14. CloseOrder 示例應(yīng)用程序的事件序列
            圖 14. CloseOrder 示例應(yīng)用程序的事件序列

            以下方法是應(yīng)用程序的入口點(diǎn),圖 14 顯示的每個(gè)步驟幾乎都由其進(jìn)行組織:


            清單 3. closeOrder 方法
            												
            																		
            public void closeOrder(int customerId) {
                ConnectionWrapper conn =
                    getConnectionWorker("java:comp/env/jdbc/DASDefault "); [1]
                JDBCAccess mediator = 
                    createAccessWorker("java:comp/env/DAS/XMLMetadata ", conn); [2]
            
                DataObject order = null;
                try {
                    order = getOpenOrderWorker(customerId, mediator); [3]
                } catch (NoCustomer nc) {
                    Logger.warn("CloseOrder app could not find specified customer. [4]
                        Prompting end user to create one or cancel transaction.", nc);
                    // ... code to notify presentation layer would go here ...
                } catch (OrderNotOpen ono) {
                    Logger.warn("CloseOrder app could not find order associated with 
                        given customer. Notifying end user.", ono); [5]
                    // ... same as above ...
                }
            
                order.set("STATUS", "CLOSED"); [6]
                persistChangesWorker(order, mediator); [7]
                closeConnectionWorker(conn); [8]
            }
            
            												
            										

            此方法的主要任務(wù)是:

            1. 獲取 JDBC 連接包裝類。
              getConnectionWorker() 代碼詳細(xì)說(shuō)明數(shù)據(jù)庫(kù)如何連接。輔助方法需要 JDBC 的 JNDI 上下文引用。

            2. 創(chuàng)建訪問(wèn)。
              輔助方法需要 ConnectionWrapper 和對(duì) metadata.xml 的 JNDI 上下文引用。

            3. 獲取客戶的開(kāi)放訂單。
              輔助方法使用中介獲取 SDO 對(duì)象圖,遍歷到與根 customer 項(xiàng)相關(guān)的 order,然后將其返回。

            4. 處理無(wú)客戶的異常情況。
              獲取開(kāi)放訂單的輔助方法可能引發(fā) NoCustomer 異常。除了記錄此情況并通知表示層之外(使用 closeOrder() 進(jìn)行),典型的異常處理還可能包括使用新連接重試,或嘗試采用名稱替代 ID 進(jìn)行查找。

            5. 處理無(wú)開(kāi)放訂單的異常情況。
              獲取開(kāi)放訂單的輔助方法可能引發(fā) OrderNotOpen 異常。對(duì)此的恰當(dāng)異常處理由讀者自行完成。

            6. 關(guān)閉訂單。
              修改 order SDO DataObject 的狀態(tài)字符串。

            7. 保存訂單。
              將 order SDO DataObject 保存到數(shù)據(jù)庫(kù)。

            8. 關(guān)閉連接。
              關(guān)閉連接。

            5. 創(chuàng)建 JDBC 連接包裝類

            以下代碼示例包含創(chuàng)建數(shù)據(jù)庫(kù)連接的輔助方法。此方法完成了圖 14 所示序列的步驟 (A) 和 (B) 的工作。


            清單 4. getConnectionWorker 方法
            												
            																		
            private ConnectionWrapper getConnectionWorker(String ctxRef) {
                Connection conn = null;
                try {
                    InitialContext ctx = new InitialContext();
                    DataSource ds = (DataSource) ctx.lookup(ctxRef);
                    conn = ds.getConnection();
                    conn.setAutoCommit(false);
                    conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
                    return ConnectionWrapperFactoryImpl.soleInstance.createConnectionWrapper(conn);
                } catch (NamingException ne) {
                    throw new CloseOrderRuntime("CloseOrder could not lookup jdbc string
                        binding: "+ctxRef, ne);
                } catch (SQLException sqle) {
                    throw new
                        CloseOrderRuntime("CloseOrder failed to make database connection", sqle);
                }
            }
            
            												
            										

            此方法的內(nèi)容對(duì)于具有 JDBC 經(jīng)驗(yàn)的 JavaEE 開(kāi)發(fā)人員非常簡(jiǎn)單。唯一特定于 JDBC DAS 代碼是從 ConnectionWrapperFactory 創(chuàng)建 ConnectionWrapper。請(qǐng)注意,此處使用了一個(gè)泛型運(yùn)行時(shí)異常重新引發(fā)假定將由 JavaEE 應(yīng)用程序中更高層處理的異常。

            6. 創(chuàng)建 JDBC 中介

            以下代碼示例包含創(chuàng)建中介的輔助方法。此方法完成了圖 14 所示序列的步驟 (C) 和 (D) 的工作。


            清單 5. createAccessWorker 方法
            												
            																		
            private JDBCAccess createAccessWorker(String ctxRef, ConnectionWrapper conn) {
                JDBCAccess mediator = null;
                String xmlPath = null;
                try {
                    InitialContext ctx = new InitialContext();
                    xmlPath = (String) ctx.lookup(ctxRef); <b>[1]</b>
                    InputStream is = getClass().getClassLoader().getResourceAsStream(xmlPath); <b>[2]</b>
                    mediator = JDBCAccessFactory.soleInstance.createAccess(is, conn); <b>[3]</b>
                } catch (NamingException ne) { <b>[4]</b>
                    throw new CloseOrderRuntime("CloseOrder could not lookup metadata string 
                        binding: "+ctxRef, ne);
                } catch (FileNotFoundException fnfe) {
                    throw new CloseOrderRuntime("CloseOrder app cannot find: "+xmlPath, fnfe);
                } catch (IOException ioe) {
                    throw new CloseOrderRuntime("CloseOrder app has filesystem error", ioe);
                } catch (AccessException me) {
                    throw new CloseOrderRuntime("Metadata inside "+xmlPath+" is invalid.", me);
                }   
                return mediator;
            }
            
            												
            										

            此方法的主要任務(wù)是:

            1. 使用 JNDI 上下文引用獲取文件名。
              采用與查詢 JDBC 數(shù)據(jù)源類似的方法檢索 XML 元數(shù)據(jù)文件名。

            2. 創(chuàng)建文件流
              使用文件名創(chuàng)建指向 XML 元數(shù)據(jù)文件的常規(guī) java.io.InputStream。

            3. 創(chuàng)建 JDBC 訪問(wèn)。
              使用 JDBCAccessFactory,并將文件流和數(shù)據(jù)庫(kù)連接包裝類作為參數(shù),以創(chuàng)建中介。

            4. 處理異常。
              此處也是使用一個(gè)泛型運(yùn)行時(shí)異常處理各種異常。

            7. 從數(shù)據(jù)庫(kù)檢索 SDO DataObject 圖

            以下代碼片段包含了從數(shù)據(jù)庫(kù)檢索 SDO 對(duì)象圖并返回客戶的開(kāi)放訂單的輔助方法。此方法完成圖 14 所示序列中的步驟 (E) 的工作。


            清單 6. getOpenOrderWorker 方法
            												
            																		
            private DataObject getOpenOrderWorker(int customerId, JDBCAccess mediator) throws NoCustomer, OrderNotOpen {
                DataObject graph = null;
                try {
                    DataObject param = mediator.getParameterDataObject();
                    param.setInt("CUST_ID", customerId); [1]
                    graph = mediator.getGraph(param); [2]
                }
                catch(AccessException me) {
                    throw new CloseOrderRuntime("CloseOrder app failed to get customer graph from 
                        mediator. CUST_ID="+customerId, me);
                }
                
                List cList = graph.getList("CUSTOMER"); [3]
                if(cList.size() == 0) {
                    throw new NoCustomer("CloseOrder app could not find customer for 
                        CUST_ID="+customerId);
                }
                DataObject customer = graph.getDataObject("CUSTOMER.0"); [4]
                
                if(customer.getInt("ORDER_ID") == 0 || graph.getList("ORDER").size() != 1) {
                    throw new OrderNotOpen("CloseOrder app did not find an open [5]
                        order for customer with CUST_ID="+customerId);
                }
                
                return customer.getDataObject("ORDER_RELATION"); [6]
            }
            
            												
            										

            此方法的主要任務(wù)是:

            1. 創(chuàng)建參數(shù)。
              創(chuàng)建一個(gè)名為 CUST_ID 的參數(shù),并將其設(shè)置為 customerId。此參數(shù)在篩選器中使用,以將 SDO 圖限制為僅包含具有元數(shù)據(jù) XML 中指定的特定 ID 的客戶。

            2. 獲取 SDO DataObject 圖。
              使用步驟 1 中構(gòu)造的參數(shù)對(duì)中介調(diào)用 getGraph 方法。此圖中應(yīng)包含客戶及其相關(guān)訂單。

            3. 檢查客戶是否存在。
              getList("CUSTOMER") 方法返回 SDO 圖中所有客戶數(shù)據(jù)對(duì)象的列表。如果大小為零,則將引發(fā) NoCustomer 應(yīng)用程序異常。

            4. 獲取客戶。
              從 SDO 圖獲取客戶。請(qǐng)注意,追加到 CUSTOMER.0 的零是必需的,用以指示要檢索 customer 列表的哪個(gè)元素(在此例中,列表中僅有一個(gè)客戶)。

            5. 檢查是否存在開(kāi)放訂單。
              如果訂單不是開(kāi)放狀態(tài),則不能對(duì)其進(jìn)行關(guān)閉操作。將檢查 OPEN_ORDER_ID 外鍵,還將檢查 order DataObject 列表是否為非零。

            6. 返回開(kāi)放訂單。
              通過(guò)遍歷元數(shù)據(jù)中定義的關(guān)系,從 customer 子圖檢索開(kāi)放訂單。

            8. 保存 SDO 圖

            以下代碼示例包含保存已更新 SDO DataObject 圖的輔助方法。此方法完成了圖 14 所示序列的步驟 (G) 的工作。


            清單 7. persistChangeWorker method
            												
            																		
            private void persistChangesWorker(DataObject graph, JDBCAccess mediator) {
                try {
                    mediator.applyChanges(graph);
                } catch(AccessException me) {
                    throw new CloseOrderRuntime("CloseOrder app failed to persist SDO graph.              
                        Access="+mediator+"\nGraph="+graph, me);
                }
            }
            
            												
            										

            9. 關(guān)閉連接

            以下代碼示例包含關(guān)閉數(shù)據(jù)庫(kù)連接的輔助方法。此代碼完成了圖 14 所示序列的步驟 (H) 的工作。


            清單 8. closeConnectionWorker 方法
            												
            																		
            private static void closeConnectionWorker(ConnectionWrapper conn) {
                try {
                    conn.getConnection().close();
                } catch (SQLException sqle) {
                    throw new CloseOrderRuntime("CloseOrder app failed to close 
                        ConnectionWrapper="+conn, sqle);
                }
            }
            
            												
            										

            10. 檢查應(yīng)用程序異常

            CloseOrderApplication 使用了以下異常,這些異常都位于 developerworks.sdo.example.exception 包內(nèi):


            清單 9. CloseOrderApplication 所使用的異常
            												
            																		
            public class CloseOrderRuntime extends RuntimeException {
                public CloseOrderRuntime() {
                    super();
                }
                public CloseOrderRuntime(String msg) {
                    super(msg);
                }
                public CloseOrderRuntime(Exception nested) {
                    super(nested);
                }
                public CloseOrderRuntime(String msg, Exception nested) {
                    super(msg, nested);
                }
            }
            
            public class NoCustomer extends Exception {
                public NoCustomer() {
                    super();
                } 
                public NoCustomer(String msg) {
                    super(msg);
                }
            }
            
            public class OrderNotOpen extends Exception {
                public OrderNotOpen() {
                    super();
                }
                public OrderNotOpen(String msg) {
                    super(msg);
                }
            }
            
            												
            										

            11. 使用 Servlet 測(cè)試應(yīng)用程序

            1. 右鍵單擊 Deployment Descriptor: CloseOrderWeb 項(xiàng)目,然后選擇 New => Servlet...

            2. 在 Name 字段輸入 TestCloseOrder,然后單擊 Next

            3. 在 Java package 中輸入 developerworks.sdo.example.test,然后單擊 Finish

            4. 插入以下代碼作為 doGet 方法的內(nèi)容:


              清單 10. 測(cè)試 Servlet
              																
              																								
              protected void doGet(HttpServletRequest request, HttpServletResponse response) throws 
                  ServletException, IOException {
              	String customerId = request.getParameter("customerId");
              	CloseOrderApplication coa = new CloseOrderApplication();
              	coa.closeOrder(Integer.parseInt(customerId));
              	response.getWriter().print("Close order request processed successfully.");
              }
              																
              														

            5. 選擇 Servers 選項(xiàng)卡,右鍵單擊 WebSphere Application Server v6.0,然后選擇 Start

            6. 再次右鍵單擊服務(wù)器,并選擇 Add and remove projects...,以將 CloseOrder EAR 項(xiàng)目部署到服務(wù)器。

            7. 部署了項(xiàng)目之后,使用以下 URL 在 Web 瀏覽器中打開(kāi)管理控制臺(tái):http://localhost:9060/admin。

            8. 選擇 Log in => Security => Global security => JAAS Configuration => J2C Authentication data => New,并按照?qǐng)D 15 所示填寫(xiě)表單。


              圖 15. 數(shù)據(jù)庫(kù)身份驗(yàn)證入口
              圖 15. 數(shù)據(jù)庫(kù)身份驗(yàn)證入口
            9. 選擇 OK,然后選擇 Save

            10. 選擇 Environment => WebSphere Variables => DB2UNIVERSAL_JDBC_DRIVER_PATH 并輸入您的 DB2 驅(qū)動(dòng)程序目錄。Windows 下的缺省值為 C:\Program Files\IBM\SQLLIB\java

            11. 選擇 Resources => JDBC Providers => New 并按照?qǐng)D 16 所示填寫(xiě)表單。


              圖 16. JDBC Provider 配置
              DB2-Provider.PNG
            12. 依次單擊 NextOKSave

            13. 選擇 DB2 Universal JDBC Driver Provider (XA) => Data sources => New

            14. 插入 jdbc/db2/Example 作為 JNDI name。

            15. 選擇 DB2 Login 作為 Component-managed authentication alias。

            16. 輸入 EXAMPLE 作為 Database name。

            17. 輸入 localhost(或 DB2 的主機(jī))作為 Server name,然后單擊 Save

            18. 為了確保數(shù)據(jù)源正常工作,請(qǐng)選擇 DB2 Universal JDBC Driver XA DataSource 旁邊的框,并單擊 Test connection

            19. 最后一個(gè)管理步驟就是 metadata.xml 文件的 JNDI 字符串綁定。選擇 Environment => Naming => Name Space Bindings => New => String => Next 并按照?qǐng)D 17 所示填寫(xiě)表單。Name Space value 中的 Name 為 string/CloseOrderApp/metadata


              圖 17. XML 文件名字符串綁定
              圖 17. XML 文件名字符串綁定
            20. 選擇 Next => FinishSave

            21. 重新啟動(dòng)服務(wù)器,以確保所有 JNDI 綁定均已更新。

            22. 若要運(yùn)行該應(yīng)用程序,請(qǐng)將以下 URL 輸入到 Web 瀏覽器中:http://localhost:9080/CloseOrderWeb/TestCloseOrder?customerId=2







            結(jié)束語(yǔ)

            JDBC Data Access Service 提供了對(duì)面向服務(wù)的體系結(jié)構(gòu)的持久化層的標(biāo)準(zhǔn)化訪問(wèn)。本文演示了 SDO DAS 如何如何適應(yīng)大型的企業(yè)部署,以及如何使用簡(jiǎn)潔且用戶友好的 XML 元數(shù)據(jù)將現(xiàn)有數(shù)據(jù)庫(kù)架構(gòu)映射到 SDO。

            posted on 2006-04-17 02:33 wsdfsdf 閱讀(438) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 技術(shù)文章

            久久99精品国产99久久| 国产成人精品久久亚洲高清不卡 | 久久精品一区二区三区不卡| 无码人妻精品一区二区三区久久久| 久久青青草原亚洲av无码| 久久电影网一区| 亚洲综合久久综合激情久久| 狠狠色丁香久久综合婷婷| 91久久精一区二区三区大全| 久久精品人人做人人妻人人玩 | MM131亚洲国产美女久久| 国产成人久久精品一区二区三区| 免费精品国产日韩热久久| 久久久久久久精品成人热色戒| 狠狠色丁香久久婷婷综合图片 | 久久天天躁狠狠躁夜夜av浪潮| 久久精品女人天堂AV麻| 久久久久亚洲AV成人网人人网站| 久久久久亚洲AV成人网| 人妻精品久久久久中文字幕| 超级97碰碰碰碰久久久久最新| 亚洲精品美女久久777777| 精品久久久久香蕉网| 91久久成人免费| 亚洲欧美久久久久9999| 色欲久久久天天天综合网 | 91久久福利国产成人精品| 久久久久久一区国产精品| 久久影院午夜理论片无码| 一本一本久久a久久综合精品蜜桃 一本一道久久综合狠狠老 | 久久精品人人做人人妻人人玩| 99国产精品久久| 热久久视久久精品18| 日本强好片久久久久久AAA| 香港aa三级久久三级| 久久综合鬼色88久久精品综合自在自线噜噜 | 人妻无码久久一区二区三区免费| 一本大道久久a久久精品综合| 欧洲性大片xxxxx久久久| 国产亚洲综合久久系列| 午夜福利91久久福利|