Java數據對象(JDO)快速入門


  JDO有一個充滿活力的社區。所以如果你正在爲你的POJO尋找持久化解決方案,JDO是一個通過JCP項目開發的標準。JDO爲POJO持久化提供了一個豐富和具有全部特徵的JSR規範,並且很多開發商正在提供競爭性的JDO實現。EJB3.0,正由Sun微系統和來自於不同的持久化開發商的專家創建,將是未來持久化模型的選擇。

  持久化Java技術對象到任何關係型數據庫都是一項富有挑戰性的任務,因爲它必須潛心於序列化層次化結構的java對象到基於表結構的數據庫,反之亦然。這個挑戰是獨一無二的,因爲將java技術對象映射到數據庫的列和記錄的方式,必須要在速度和效率上同時達到最優化。java數據對象(JDO)規範,JSR-12,爲使用標準的方式來透明地持久化簡單java技術對象和訪問數據庫定義了API。使用JDO,java應用程序開發者可以在不使用任何數據庫特定代碼的情況下編寫代碼訪問底層的數據存儲。JDO被設計成在一個企業架構的多重層次中工作,包括java平臺、標準版(java SE,以前被稱爲J2SE)、Web層和應用服務器

  本文提供了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實例的生命週期

  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實例各狀態之間的轉換。


圖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%/lib/jdo.jar;%JDO-HOME%/lib/jdori.jar;
%JDO-HOME%/jdori-enhancer.jar com.sun.jdori.enhancer.Main -d
/enhanced -s . -f path/tp/package.jdo path/to/theclasses.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。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章