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

Castor JDO 入門實戰:Java 物件與關聯式資料庫的開源映射橋樑

     編輯:Java 程式設計入門

前言:為什麼需要 Castor JDO?

企業應用核心難題:將豐富領域模型 (Java 物件圖) 持久化到關聯式資料庫。手寫 JDBC/SQL 維護成本高、易錯、難移植。Castor JDO (Java Data Objects) 作為早期開源 ORM 先驅 (1999 首發),提供 100% 純 Java、基於 XML 映射檔、支援多種資料庫的資料綁定框架,至今仍是理解 ORM 核心概念的優秀教材。

核心架構:雙模型 + 映射描述符

範例領域:產品目錄

  • 關聯模型 (ER 圖):prod、comp、prod_detail、category、category_prod、prod_group 表
  • 物件模型 (UML 類圖):Product、Computer、ProductDetail、Category、ProductGroup 類
  • 一對一映射:表 ↔ 類、欄位 ↔ 屬性

Product 物件定義 (POJO + Persistent)

public class Product implements Persistent {
    private int _id;
    private String _name;
    private float _price;
    private ProductGroup _group;
    private Database _db;  // Castor 注入
    
    // 關聯集合
    private Vector _details = new Vector();      // 1:N ProductDetail
    private Vector _categories = new Vector();   // M:N Category
    
    // Getter/Setter...
    
    // 關聯管理便利方法
    public void addDetail(ProductDetail detail) {
        _details.add(detail);
        detail.setProduct(this);  // 維護雙向關聯
    }
    
    public void addCategory(Category category) {
        if (!_categories.contains(category)) {
            _categories.addElement(category);
            category.addProduct(this);
        }
    }
}

映射描述符:XML 驅動的 ORM 核心

映射檔 `mapping.xml` 定義類↔表、屬性↔欄位、關聯↔外鍵/關聯表對應。Castor 利用自家 Castor XML 解析映射檔,實現「XML 配置 Java 物件」元模型。

Product 映射範例

<class name="myapp.Product" identity="id">
  <description>Product definition</description>
  <map-to table="prod" xml="product" />
  
  <field name="id" type="integer">
    <sql name="id" type="integer" />
  </field>
  <field name="name" type="string">
    <sql name="name" type="char" />
  </field>
  <field name="price" type="float">
    <sql name="price" type="numeric" />
  </field>
  
  <!-- 多對一:多產品屬同一群組 -->
  <field name="group" type="myapp.ProductGroup">
    <sql name="group_id" />
  </field>
  
  <!-- 一對多:一產品多明細 -->
  <field name="details" type="myapp.ProductDetail" 
         required="true" collection="vector">
    <sql many-key="prod_id" />
  </field>
  
  <!-- 多對多:產品-分類 -->
  <field name="categories" type="myapp.Category" 
         required="true" collection="vector">
    <sql name="category_id" many-table="category_prod" many-key="prod_id" />
  </field>
</class>

關鍵映射屬性解析

屬性/元素作用
`identity`指定主鍵屬性 (對應資料庫 PK)
`map-to table`對應資料庫表名
`field type`Java 型別,決定 TypeConverter 選擇
`sql name/type`資料庫欄位名與 SQL 型別
`collection="vector"`集合型別 (支援 vector/arraylist/set/map)
`many-key`一對多關聯的外鍵欄位 (在「多」方表中)
`many-table/many-key`多對多關聯的中間表與雙向外鍵
`depends`標記從屬物件 (生命週期綁定主物件)

進階映射特性

繼承映射:Java 繼承 vs 關聯繼承

<!-- Computer 繼承 Product -->
<class name="myapp.Computer" extends="myapp.Product" identity="id">
  <map-to table="computer" xml="computer" />
  <field name="id" type="integer"><sql name="id" type="integer"/></field>
  <field name="cpu" type="string"><sql name="cpu" type="char"/></field>
</class>
  • 資料庫採用「共享主鍵」策略:computer 表主鍵同時是 prod 表外鍵
  • 查詢 Computer 時自動 JOIN prod 表取得基礎屬性

從屬 vs 關聯:生命週期擁有權

<class name="myapp.ProductDetail" identity="id" depends="myapp.Product">
  <map-to table="prod_detail" xml="detail" />
  <field name="product" type="myapp.Product">
    <sql name="prod_id" />
  </field>
  ...
</class>
  • 關聯 (獨立) 物件:無 `depends`,可獨立 CRUD (如 Product、Category)
  • 從屬物件:有 `depends="Master"`,只能透過主物件導航操作 (如 ProductDetail 必須透過 Product 存取)
  • 每個從屬物件僅能有一個主物件

物件查詢語言 (OQL):面向物件模型查詢

Castor 實作 ODMG 3.0 OQL 子集,語法類 SQL 但查詢物件圖而非資料表,支援多資料庫自動轉譯 SQL。

常用查詢範例

// 所有 Computer
SELECT c FROM myapp.Computer c

// ID=1234 的 Computer
SELECT c FROM myapp.Computer c WHERE c.id = $1
query.bind(1234)

// 名稱模糊匹配
SELECT c FROM myapp.Computer c WHERE c.name LIKE $1
query.bind("%abcd%")

// ID 列表查詢
SELECT c FROM myapp.Computer c WHERE c.id IN LIST ($1, $2, $3)
query.bind(97); query.bind(11); query.bind(7)

支援別名 (c)、參數綁定 ($1, $2...)、路徑導航 (c.group.name)。

事務管理:短事務 vs 長事務

短事務 (標準)

單一資料庫事務邊界內完成載入/修改/提交。適用於短時業務操作。

長事務 (樂觀鎖模式)

解決 Web 應用「讀取 → 用戶思考/編輯 → 提交」跨越長時間 (甚至天) 的場景,避免長時間持有資料庫寫鎖。

// 第一階段:唯讀載入 (短事務 1)
public LineItem getLineItem() {
    db.begin();
    LineItem item = (LineItem) db.load(LineItem.class, id, Database.ReadOnly);
    db.commit();
    return item;  // 物件脫離事務上下文,用戶可自由編輯
}

// 第二階段:更新提交 (短事務 2)
public void updateOrder(LineItem item) {
    db.begin();
    db.update(item);  // 重新附加到事務上下文
    db.commit();
}

髒檢查 (Dirty Check) 保護長事務

  • 映射檔 `` 啟用
  • 物件實作 `Timestampable` 回調介面
  • 第一階段載入時記錄時間戳,第二階段提交前比對,防止併發修改覆蓋

資料庫支援矩陣

DB2、HypersonicSQL、Informix、InstantDB、Interbase、MySQL、Oracle、PostgreSQL、SAP DB、SQL Server、Sybase、Generic (標準 JDBC 回退)。新增資料庫支援只需實作對應的 `TypeConverter` 與 SQL 方言適配。

現代視角:Castor JDO 的歷史定位與啟示

Castor JDO 雖非主流選擇,但其「XML 映射驅動」、「物件標識追蹤」、「從屬/關聯區分」、「OQL 面向物件查詢」、「長事務樂觀鎖」等核心設計思想,深刻影響後續 Hibernate/JPA 發展。研讀 Castor 原始碼與文檔,是理解 ORM 內部機制、排查疑難雜癥、設計自訂持久層框架的寶貴資產。

總結

Castor JDO 以純 Java、XML 映射、多資料庫支援,提供了早期企業級 ORM 的完整解決方案。掌握其映射描述符精髓、關聯建模藝術、OQL 查詢思維、長事務模式,能幫助開發者透過現象看本質,在現代 JPA/Hibernate/Spring Data 技術棧中做出更明智的架構決策與效能調優。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
時代代表技術核心貢獻
2000-2005Castor JDO, Hibernate 1/2確立 ORM 基礎概念:映射檔、Session/Database、延遲載入、查詢語言
2006-2010Hibernate 3, JPA 1.0, TopLink/EclipseLink標準化 (JPA)、註解配置、實體管理器、Criteria API
2011-至今Spring Data JPA, Hibernate 5/6, jOOQ, MyBatisRepository 抽象、反應式、Kotlin 協程、類型安全 SQL