top
Loading...
Java數據對象(JDO)快速入門
本文提供了JDO的指南,它包含了JDO的基本要素,并且提供了使用JDO持久化Java技術對象的示例代碼。

引言

持久化,在程序退出后信息可以長期保存,在Java語言中可以使用不同的選擇完成。最簡單的是文件I/O,但是這種方式不適合在企業級存儲中使用(原因很明顯)。其它的選擇包括以下幾種:

·序列化(Serialization):API簡單,不支持查詢、多用戶共享、事務處理和局部數據讀取或更新。另外,它不適合大容量數據存儲。

·JDBC軟件:具有完全訪問的SQL數據的功能。JDBC要求開發者必須顯式地管理字段值以及把它們映射到關系數據庫的表。在這種情況下,開發者必須熟悉另外一種開發語言(例如,查詢語言SQL)。

·EJB架構容器管理持久性(CMP):作為Java企業級平臺(Java EE,以前被稱為J2EE)組件模型的一部分,CMP為EJB容器提供了一種簡便的對象持久化服務。然而,它不是一種對于Java平臺的普通持久化工具。

一種可行的選擇是JDO API,它提供了一種標準的方式,使用Java技術完成對象的持久化,通過結合XML元數據和增強的字節碼簡化了開發復雜性和降低開發成本。

JDO架構

高級的JDO API為開發者透明地存儲數據提供了接口,開發者不必為每一種新的持久化數據存儲而學習一種新的數據庫訪問語言(例如SQL)。JDO也可以使用低級的API(例如JDBC)來存儲數據。它使開發者可以編寫Java代碼透明地訪問底層的數據存儲,而不需要使用數據庫特定代碼。JDO在JCP的項目中作為一個JSR開發:JDO1.0,從2002年開始存在,是JSR-12;JDO2.0,2005年初被核準并且正在開發中,是JSR-243。

JDO2.0是一個適合于簡單Java對象(POJOs)持久化特點的JSR規范,很多廠家都在提供競爭性的實現。另外,很多廠家很可能在同一個的產品中實現JDO2.0和EJB3.0。這就允許你同時使用兩種API,為你提供了逐漸遷移到EJB3.0 POJO的簡單方法,將會變為持久化模型的選擇。

JDO架構(如圖1所示)的兩個主要目的就是,為Java應用程序開發者提供透明地以Java技術為核心的訪問持久化信息的方式,使數據存儲的可插入式實現集成到應用服務器中。

JDO架構

圖1 JDO架構

請注意,JDO沒有定義數據存儲的類型:你可以使用同樣的代碼持久化的你的Java對象到關系型數據庫、對象型數據庫、XML和任何數據存儲。

使用JDO的好處主要包括以下幾點:

·簡便性(Portability):使用JDO API編寫的程序可以在不同開發商的多種可用的實現上運行,不用修改一行代碼,甚至不用重新編譯。

·透明地訪問數據庫(Transparent database access):應用程序開發者編寫代碼透明地訪問底層數據存儲,而不需要使用任何數據庫特定代碼。

·易用性(Ease of use):JDO API允許開發者只需要關注他們自己范圍內的數據模型(Domain Object Model,DOM),而持久化的細節就留給JDO實現。

·高性能(High Performance):Java應用程序開發者不需要擔心數據訪問的性能優化,因為這個任務已經委派給了JDO實現,它通過改善數據訪問的模式以獲得最佳性能。

·和EJB集成(Integration with EJB):應用程序可以利用EJB的特征,例如遠程信息處理、自動分布式事務協調和貫穿整個企業級應用使用同樣的DOMs實現安全性。

使用JDO,vs. EJB和JDBC

JDO并不意味著要取代JDBC。它們是兩種以各自獨一無二的能力互相補充的技術,具有不同技術背景和開發目的開發者可以使用二者中的一個。例如。JDBC通過直接的數據庫訪問控制和緩存管理,提供給開發者更大的彈性。JDBC是一種在工業界被廣泛認可的成熟技術。另一方面,JDO,通過隱藏SQL提供給開發者更大的簡便性。它將Java平臺開發者從必須熟悉或學習SQL中解脫出來,而將精力集中在DOM上,同時JDO管理在持久存儲中對象存儲的字段到字段的細節。

JDO被設計成EJB的補充。CMP為容器提供簡便的持久化,而JDO可以以兩種方式集成到EJB中:(1)通過會話Bean,它含有JDO Persistence-capable類(會話Bean的持久化助手類)用來實現依賴對象;(2)通過實體Bean,它含有被用作BMP和CMP代理的JDO Persistence-capable類。

你可以學習更多關于JDO和JDBC之間的關系,還有EJB2.0 CMP和JDO之間的關系。

POJO之路

JDO和EJB之間在持久化模型上顯著的差別曾經在開發者中間引起了混亂。作為回應,Sun微系統正領導一個社區項目為Java技術社區創建POJO持久化模型。這個項目在JSR-220的贊助下執行,由Linda DeMichiel領導。JDO2.0(JSR-243)的專家組成員被邀請加入到EJB3.0(JSR-220)專家組中。

創建POJO持久化模型的目的是為所有使用Java SE和Java EE平臺的Java應用程序開發者提供一個對象—關系(object-relational)映射工具。值得注意的是Oracle正以co-specification lead的身份加入到Sun EJB3.0。EJB3.0的公眾評論草案已經可以得到。

JSR-243(JDO2.0)遵循了那些來自于JSRs220和243規范的領導寫給Java技術社區的信件所描述的輪廓。

JDO2.0并不打算作為EJB3.0持久化特定API的集中,而是作為JDO1.0.2的發展。但是JDO的POJO持久化模型和EJB3.0之間的類似處,使得JDO的客戶當使用JDO2.0滿足立即的需求時,可以很容易的接受EJB3.0持久化模型。另外,JSR-243打算將JDOQL用作一種關于EJB3.0持久化數據的可選查詢語言。這種語言了已經被更新從而可以更好地對EJB3.0使用。

要了解更多關于持久化模型的知識,請查看EJB/JDO持久化FAQ。

JDO Class類型

在JDO中一共有三種類型的類:

·Persistence-capable:這種類型代表那些實例可以被持久化到一個數據存儲中的類。請注意,這些類在JDO環境中被使用之前,需要通過JDO元數據規范進行加強。

·Persistence-aware:這些類操縱persistence-capable類。JDOHelper類包含了一些方法,它們允許詢問一個persistence-capable類的實例的持久化狀態。請注意,這些類使用最小化的JDO元數據加強。

·Normal:這些不可被持久化,并且對持久化一無所知。另外它們不需要JDO元數據。

JDO實例的生命周期

JDO管理一個對象從創建到刪除的生命周期。在它的生命周期,JDO實例不斷地轉換它的狀態,直到最后被Java虛擬機(JVM)作為垃圾回收。狀態的轉換使用PersistenceManager類的方法完成,包括TransactionManager——例如makePersistent()、makeTransient()、deletePersistent()——和提交或者回滾更改。

表1顯示JDO規范定義的10種狀態。前面的七種是必須的,后面的三種是可選的。如果一個實現不支持某些操作,那么就不會獲得三種可選的狀態。

表1 JDO生命周期

狀態描述
Transient任何使用開發者定義的構造函數創建的對象,都不包括持久化環境。一個瞬時實例沒有JDO身份。
Persistent-new被應用程序組件請求的任何對象都變為持久的,通過使用PersistenceManager類的makePersistent()。這樣的一個對象將會擁有一個分配的JDO身份。
Persistent-dirty在當前事務中被改變的持久對象。
Hollow代表在數據存儲中特定數據的持久對象,但是在它的實例中沒有包含值。
Persistent-clean代表在數據存儲中的特定事務數據的持久對象,并且它們的數據在當前事務處理中還沒有被改變。
Persistent-deleted代表在數據存儲中的特定數據的持久對象,并且在當前事務處理中已經被刪除。
Persistent-new-deleted在同一個事務處理中最近被持久化和刪除的持久對象。
Persistent-nontransactional代表數據存儲中的數據的持久對象,當前它們的值已經被裝載,但是還沒有事務處理一致。
Transient-client代表一個瞬時事務處理實例的持久對象,它們的數據在當前事務中還沒有被改變。
Transient-dirty代表一個瞬時事務處理實例的持久對象,它們的數據在當前事務中已經被改變。

圖2顯示了JDO實例各狀態之間的轉換。

JDO實例狀態轉換
圖2 JDO實例的狀態轉換

本文稍后的代碼片斷,將示范如何執行我們剛剛討論的操作。

JDO參考實現

JDO參考實現,來自于Sun微系統,已經可用,一同發行的還有一種被稱為fstore的基于文件的存儲機制。Sun已經把JDO捐獻給開源社區。JDO1.0和JDO2.0將會作為Apache JDO項目的一部分進行開發。但是由于時間的限制,JDO2.0的參考實現并不是作為Apache項目建立的,而是作為一個JPOX 發行。一些商業實現也是可用的。

JDO編程模型

JDO定義了兩種類型的接口:JDO API(在javax.jdo包中)和JDO服務提供者接口(SPI)(在javax.jdo.spi包中)。JDO API面向應用程序開發者,而JDO SPI面向容器提供者,和JDO賣主。

一個應用程序包含兩個主要的接口:

·PersistenceManagerFactory代表了應用程序開發者用來獲得PersistenceManager實例的訪問點。這個接口的實例可以被配置和序列化以備后來使用。然而,需要注意的是,一旦第一個PersistenceManager實例從PersistenceManagerFactory中被獲得,這個工廠就不再是可配置。你可以使用下面的代碼來獲得PersistenceManagerFactory。

// 為JDO實現和數據存儲設置一些屬性
Properties props = new Properties();
props.put(...);
// 得到一個PersistenceManagerFactory
PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory (props);

·PersistenceManager是JDO-aware應用部分的主要接口。它提供了方法來持久化一個對象,也可以重新得到持久對象和將它們從持久存儲中移除。可以使用下面的方法獲得PersistenceManager。

PersistenceManager pm = pmf.getPersistenceManager ();

一旦獲得了PersistenceManager對象后,應用程序就可以一些任務,例如:持久化一個對象、從持久數據中獲得一個對象、從持久數據中刪除一個對象、更新一個對象等等。

接下來的代碼片斷示范了如何持久化一個對象,它更新一個對象的狀態從Transient到Hollow。

Employee emp = new Employee("Sarah Jones", 23, 37000.00);
Transaction tx;
try {
tx = pm.currentTransaction();
tx.begin();
pm.makePersistent(emp);
tx.commit();
} catch (Exception e) {
if(tx.isActive()) {
tx.rollback();
}
}

從持久數據中獲得一個對象同樣簡單,你可以使用Extent(一個信息的持有者)或者Query(提供了更精確的過濾)。下面是一個使用Extent的例子:

try {
tx = pm.currentTransaction();
tx.begin();
Extend ex = pm.getExtent(Employee.class, true);
Iterator i = ex.iterator();
while(i.hasNext()) {
Employee obj = (Employee) i.next();
}
tx.commit();
} catch (Exception e) {
if(tx.isActive()) {
tx.rollback();
}
}

最后,從持久數據中刪除一個對象也可以簡單完成,首先獲得一個從持久數據中獲得一個對象,然后調用deletePersistent(obj)方法。

查詢對象

JDO規范要求開發商必須提供使用JDOQL的查詢能力,JDOQL是一種面向圍繞被持久化對象的查詢語言。PersistenceManager類定義了構造Query實現類的實例的方法。一個查詢過濾器可以被指定為一個布爾表達式,就像SQL的布爾操作符。

生命周期開發:在你的應用程序中使用JDO

可以通過以下六個步驟建立一個JDO應用:

1. 設計你的范圍內的將會正常使用的類。對一個要求持久化的類的唯一要求就是它要有一個默認構造函數,訪問權限可能是private。

2. 使用元數據定義持久化定義:在這個步驟中,你編寫元數據,指定那些類和字段應該被持久化等等。這個文件可以包含對于一個類或一個或者多個包含持久類的包的持久化信息。一個類的元數據文件的名稱是這個類的名字加上“.jdo”后綴,注意,這個文件必須放在和.class文件相同的目錄中。對于整個包的元數據文件的必須包含在一個稱作package.jdo的文件中。元數據文件可以使用XDoclet或手動開發。下面是一個簡單的對于兩個類的元數據文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jdo SYSTEM "jdo.dtd">
<jdo>
<package name="com.xyz.hr">
<class name="Employee" identity-type="application" objectidclass="EmployeeKey">
<field name="name" primary-key="true">
<extension vendor-name="sunw" key="index" value="btree"/>
</field>
<field name="salary" default-fetch-group="true"/>
<field name="dept">
<extension vendor-name="sunw" key="inverse" value="emps"/>
</field>
<field name="boss"/>
</class>

<class name="Department" identity-type="application" objectidclass="DepartmentKey">
<field name="name" primary-key="true"/>
<field name="emps">
<collection element-type="Employee">
<extension vendor-name="sunw" key="element-inverse" value="dept"/>
</collection>
</field>
</class>
</package>
</jdo>


3. 編譯這些類,并且使用JDO加強器來加強它們。任何persistence-capable類的實例在被JDO持久化引擎管理之前必須被加強。JDO字節碼加強器通過對類定義特定的改變來裝換這個類,使得任何持久實例可以和數據存儲中的數據描述保持同步。和參考實現一起發行的JDO加強器,能夠從Sun微系統得到,可以使用如下的方式運行:

prompt> java -classpath
%JDO-HOME%libjdo.jar;%JDO-HOME%libjdori.jar;
%JDO-HOME%jdori-enhancer.jar com.sun.jdori.enhancer.Main -d
enhanced -s . -f pathppackage.jdo pathoheclasses.class

注意:對JDO加強器最重要的參數是一個.jdo文件的名字和.class文件的名字。另外,

·-d選項指定輸出文件的目標文件夾;

·-s選項指定jdo和class文件的源文件夾;

·-f選項強制重寫輸出文件。

如果忽略這個步驟,那么當你運行應用程序和持久化一個對象時將會拋出ClassNotPersistenceCapableException異常。

4. 為被持久化的類建立數據庫表。如果你已經有了一個數據庫方案,那么這一步是可選的。基本上,你必須建立表、索引和在JDO元數據文件中為類定義的外鍵。有些JDO實現包含一個方案工具,可以根據JDO元數據文件產生所有的這些東西。

5. 編寫代碼來持久化你的對象。在這個步驟中,你要指定那些類在什么時間被實際持久化。正如前面提到的,最初的步驟是獲得一個PersistenceManager的使用權。

6. 運行你的應用程序。使用java命令,并且包含必要的.jar文件在你的classpath中。

結束

JDO提供了基于接口的數據存儲定義和事務處理,以及持久存儲的數據到本地java技術對象的轉換和選擇。它致力于三種情況的需求:

(1)一種持久保存Java技術對象到事務性數據存儲的標準。

(2)一種對待關系性數據庫數據像Java技術對象一樣的標準方式。

(3)一種聯合那些對象定義事務性語義的標準方式。

JDO API,僅僅是由一些接口組成,非常便于學習和使用,但是更重要的是它為對象持久化定義了一種標準。今后將會有很多JDO實現供選擇,其中有些將是免費的。JDO允許你通過使用POJO來獲得它的簡便性,并非使用私有的API。

JDO有一個充滿活力的社區。所以如果你正在為你的POJO尋找持久化解決方案,JDO是一個通過JCP項目開發的標準。JDO為POJO持久化提供了一個豐富和具有全部特征的JSR規范,并且很多開發商正在提供競爭性的JDO實現。EJB3.0,正由Sun微系統和來自于不同的持久化開發商的專家創建,將是未來持久化模型的選擇。
作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗