JDO (Java Data Objects) 為 JCP 較早完成的規範 (JSR 12),規範化資料持久化存儲,已有眾多商業產品與開源專案實作。作為企業級持久層技術選型關鍵選項,深度研究其可行性極具價值。
javax.jdo.PersistenceCapable 介面Book.jdo 中繼資料檔,經位元碼增強工具處理:javac Book.javajava com.sun.jdori.enhancer.Main Book.class Book.jdo增強後類別可跨 JDO 實作使用,無需重新編譯/增強。增強過程插入程式碼攔截 set 方法,追蹤欄位變更,持久化時僅處理變更欄位。
Book book = new Book();
book.setISBN("isbn-1234567");
book.setName("Java設計模式");
PersistenceManager pm = pmf.getPersistenceManager();
pm.currentTransaction().begin();
pm.makePersistent(book); // 此後 book 成為持久物件
pm.currentTransaction().commit();
透過 vendor-extension 詳細描述儲存特性(對應資料表、欄位映射等)。
Extent extent = pm.getExtent(Book.class, true); // true 含子類
Iterator it = extent.iterator();
while (it.hasNext()) {
Book b = (Book) it.next();
System.out.println(b.getISBN());
}
extent.closeAll();
String filter = "((String)name).startsWith(\"Java設計模式\") && publishDate < today";
Query query = pm.newQuery(Book.class, filter);
query.declareImports("import java.util.Date");
query.declareParameters("Date today");
Date today = new Date();
Collection results = (Collection) query.execute(today);
declareParameters 宣告變數,execute 傳入實值——類似 JDBC PreparedStatement 參數綁定query.setOrdering("publishDate descending, name ascending");
public void updateBookPublishDate(String isbn, Date newDate) {
PersistenceManager pm = null;
try {
pm = pmf.getPersistenceManager();
Object oid = pm.newObjectIdInstance(Book.class, isbn); // 主鍵查找
Book book = (Book) pm.getObjectById(oid, true);
book.setPublishDate(newDate); // 透明持久化,提交時自動同步
} catch (Exception e) {
ctx.setRollbackOnly();
throw new Exception(e);
} finally {
if (pm != null && !pm.isClosed()) pm.close();
}
}
關鍵機制:JDO 如何知道用 ISBN 尋找?需在中繼資料 (.jdo) 或註解中定義主鍵欄位。
| 優勢 | 挑戰 |
|---|---|
| 標準化 API,廠商中立 | 早期版本 (1.0) 功能較弱,查詢能力有限 |
| 透明持久化,零侵入業務邏輯 | 位元碼增強步驟增加建構複雜度 |
| 支援繼承、關係映射 | 大型專案效能調校需深度專業 |
| 與 EJB CMP 互補(非容器環境亦可用) | 社群關注度逐漸轉向 JPA |
JDO 為企業級持久層提供了標準化、透明、物件導向的解決方案。雖 JPA (EJB 3.0) 後來居上整合了 JDO 精華,但 JDO 獨立於容器、適用於 Java SE 環境的特性,在特定架構(如富客戶端、獨立服務)下仍具不可替代價值。技術選型時應依架構邊界、團隊熟悉度、長期演進路線綜合評估。