首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 數據對象技術 (JDO) 核心原理與實戰入門

     編輯:Java 相關知識

背景:為什麼需要 JDO?

Java 開發面臨多種持久化選擇,各有痛點:

技術痛點
序列化不支援事務、查詢、多用戶共享;粒度固定,難維護
JDBC雙重範式(物件 vs 關聯),手工映射繁瑣,喪失 OO 優勢
EJB CMP分散式架構重、資源消耗大、需容器、建模限制多

JDO 目標:專注物件模型設計,透明持久化,支援多種資料源,輕量級、可嵌入、可整合 EJB。

JDO 核心架構

  • PersistenceCapable:經增強的可持久化類別(位元組碼增強)。
  • PersistenceManager:核心介面,管理物件生命週期(makePersistent, deletePersistent, query 等)。
  • Query:JDOQL(類 SQL 查詢語言),針對物件模型查詢。
  • Transaction:ACID 事務邊界。
  • DataStore:抽象資料源(RDBMS、ODBMS、檔案、XML 等)。

定義可持久化類別:Movie 案例


package com.mediamania.prototype;

import java.util.*;
import java.util.Date;
import java.text.*;

public class Movie {
    // JDO 要求:無參建構子(可 private)
    private Movie() {}
    
    public Movie(String title, Date release, int duration, String rating, String genres) {
        this.title = title;
        this.releaseDate = release;
        this.runningTime = duration;
        this.rating = rating;
        this.genres = genres;
        this.cast = new HashSet<>();
    }
    
    // 基本屬性(標準 Java 型別)
    private String title;
    private Date releaseDate;
    private int runningTime;
    private String rating;
    private String webSite;
    private String genres;
    
    // 關聯:一對多(Movie -> Role)
    private Set cast; // 元素型別: Role
    
    // 業務方法(非 JDO 強制,但建議封裝集合操作)
    public void addRole(Role role) { cast.add(role); }
    public Set getCast() { return Collections.unmodifiableSet(cast); }
    
    // 靜態欄位不持久化
    private static SimpleDateFormat yearFmt = new SimpleDateFormat("yyyy");
    public static final String[] MPAA_RATINGS = {"G","PG","PG-13","R","NC-17","NR"};
    
    // Getter/Setter 省略...
    public String getTitle() { return title; }
    public Date getReleaseDate() { return releaseDate; }
    public String getRating() { return rating; }
    public int getRunningTime() { return runningTime; }
    public void setWebSite(String site) { webSite = site; }
    public String getWebSite() { return webSite; }
    public String getGenres() { return genres; }
    
    // 工具方法
    public static Date parseReleaseDate(String val) {
        try { return yearFmt.parse(val); } catch (ParseException e) { return null; }
    }
    public String formatReleaseDate() { return yearFmt.format(releaseDate); }
}

關聯建模:Actor 與 Role


// Actor.java
public class Actor {
    private Actor() {}
    public Actor(String name) { this.name = name; }
    private String name;
    private Set roles = new HashSet<>();
    public void addRole(Role role) { roles.add(role); }
    public Set getRoles() { return Collections.unmodifiableSet(roles); }
    // getter/setter...
}

// Role.java (關聯實體,攜帶屬性)
public class Role {
    private Role() {}
    public Role(Movie movie, Actor actor, String roleName) {
        this.movie = movie; this.actor = actor; this.roleName = roleName;
        movie.addRole(this); actor.addRole(this); // 雙向維護
    }
    private Movie movie;
    private Actor actor;
    private String roleName; // 屬性:角色名
    // getter/setter...
}

JDO 元資料配置

可用 .jdo XML 檔或 Annotation(JDO 2.0+)定義映射。XML 範例:





    
        
            
            
            
            
            
            
            
                
            
        
        
            
            
                
            
        
        
            
            
            
        
    

核心 API 實戰


import javax.jdo.*;
import java.util.Date;

public class JdoDemo {
    public static void main(String[] args) {
        // 1. 取得 PersistenceManagerFactory (通常單例、線程安全)
        PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("transactions-optional");
        
        // 2. 開啟 PersistenceManager (非線程安全,請求範圍)
        PersistenceManager pm = pmf.getPersistenceManager();
        Transaction tx = pm.currentTransaction();
        
        try {
            tx.begin();
            
            // 建立物件圖
            Movie movie = new Movie("Inception", new Date(), 148, "PG-13", "Sci-Fi,Action");
            Actor leo = new Actor("Leonardo DiCaprio");
            Actor ellen = new Actor("Elliot Page");
            new Role(movie, leo, "Cobb");
            new Role(movie, ellen, "Ariadne");
            
            // 持久化:透過達到關聯自動級聯
            pm.makePersistent(movie);
            
            tx.commit();
            System.out.println("持久化成功,Movie ID: " + movie.getId()); // 假設有身份欄位
        } finally {
            if (tx.isActive()) tx.rollback();
            pm.close();
        }
        
        // 查詢範例 (JDOQL)
        pm = pmf.getPersistenceManager();
        try {
            Query query = pm.newQuery(Movie.class, "genres == 'Sci-Fi'");
            List results = (List) query.execute();
            for (Movie m : results) {
                System.out.println(m.getTitle() + " - " + m.getCast().size() + " roles");
            }
        } finally {
            pm.close();
        }
    }
}

JDO vs 其他技術定位

特性JDOJPA/HibernateJDBCEJB CMP
物件透明度高 (增強後無侵入)高 (Annotation)無中
查詢語言JDOQL (物件導向)JPQL/CriteriaSQLEJB QL
資料源支援RDBMS, ODBMS, XML, 檔案...主要 RDBMSRDBMSRDBMS
事務支援本地/全域 (JTA)本地/全域手工全域 (容器管理)
運行環境Java SE/EE, 嵌入式Java SE/EEJava SE/EEJava EE 容器
學習曲線中中低低高

現代視角:JDO 的地位與繼承者

  • JDO 1.0 (2002) → 2.0 (2006) → 3.0 (2014, Apache JDO)。
  • JPA (Java Persistence API) 整合了 JDO 核心思想,成為 Java EE 標準,Hibernate、EclipseLink、OpenJPA 為主流實現。
  • JDO 仍在特定領域活躍:非關聯資料庫(如 ObjectDB、Versant)、嵌入式系統、舊系統維護。
  • Google App Engine 早期資料儲存即基於 JDO/JPA。

總結

JDO 開創了「透明物件持久化」先河,讓開發者專注領域模型而非 SQL 映射。雖然 JPA 成為主流標準,但理解 JDO 核心概念(增強、PM、JDOQL、多資料源抽象)有助於深度掌握現代 ORM 框架底層原理。新專案建議優先採用 JPA/Hibernate,除非有明確非關聯資料源需求。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved