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

db4o 實戰指南:陣列與集合的持久化、查詢與級聯更新

     編輯:Java 相關知識

前言:多樣性關係在對象數據庫中的自然表達

關係型資料庫需透過連接表建模一對多、多對多,而在 db4o 這類原生對象數據庫中,直接以 Java 集合 (List/Set) 或陣列 作為物件欄位即可自然表達多樣性關係,無需額外映射配置。本文以「家庭成員」領域模型為例,示範陣列與 ArrayList 的存儲、查詢、激活深度控制、級聯更新與刪除完整流程。

領域模型:Person、Address、多樣性關係

public class Address { // 簡單值物件
    String street, city, state, zip;
    // getter/setter、equals/hashCode/toString
}

public class Person {
    String firstName, lastName;
    Gender gender; int age; Mood mood;
    Person spouse;                    // 一對一
    Address[] addresses = new Address[3]; // 固定陣列:家庭/工作/度假
    List<Person> children = new ArrayList<>(); // 一對多集合
    Person mother, father;            // 反向引用形成循環圖

    // 業務方法:haveBaby() 同時維護雙向關係
    public Person haveBaby(String name, Gender gender) {
        if (this.gender == Gender.MALE) throw new UnsupportedOperationException("Biological impossibility!");
        if (spouse == null) throw new UnsupportedOperationException("Ethical impossibility!");
        Person child = new Person(name, this.lastName, gender, 0, Mood.CRANKY);
        child.father = this.spouse; child.mother = this;
        this.children.add(child); this.spouse.children.add(child);
        return child;
    }
    // getter/setter、equals/hashCode/toString
}

存儲:單一根物件即可遞歸持久化整個物件圖

ObjectContainer db = Db4o.openFile("persons.data");
Person bruce = new Person("Bruce", "Tate", Gender.MALE, 29, Mood.HAPPY);
Person maggie = new Person("Maggie", "Tate", Gender.FEMALE, 29, Mood.HAPPY);
bruce.setSpouse(maggie);
// 設定地址、生小孩...
db.store(bruce); // 僅存儲 bruce,可達物件 (maggie、children、addresses) 自動遞歸存儲
db.commit();
db4o 透過「可達性」判斷持久化邊界:從根物件走訪所有非 transient 字段,自動處理循環引用與共享引用。

查詢:Predicate API 與集合元素的獨立身份

1. 查詢父親並驗證地址陣列

List<Person> males = db.query(new Predicate<Person>() {
    public boolean match(Person p) {
        return "Tate".equals(p.getLastName()) && p.getGender() == Gender.MALE;
    }
});
Person bruce = males.get(0);
assert bruce.getHomeAddress().equals(new Address("5 Maple Drive", "Austin", "TX", "12345"));

2. 遍歷集合關係

int n = 0;
for (Person child : bruce.getChildren()) { // 返回 Iterator
    if (n==0) assert "Kayla".equals(child.getFirstName());
    if (n==1) assert "Julia".equals(child.getFirstName());
    n++;
}

3. 集合元素也是獨立查詢目標

List<Person> girls = db.query(new Predicate<Person>() {
    public boolean match(Person p) { return p.getGender() == Gender.FEMALE; }
});
// girls 將包含 maggie、kayla、julia —— 集合內 Person 為一級實體,不僅屬於父親

4. 跨查詢保持物件同一性

Person maggie = db.query(...).next(); // 查詢母親
Person julia = db.query(...).next();  // 查詢女兒
assert julia.getMother() == maggie;   // 同一物件實例,雙向引用完好
激活深度:若查詢配置的激活深度不足以到達 mother 欄位 (需再跳一層),則 getMother() 返回 null。需根據導航路徑設定足夠深度。

更新:級聯更新與激活深度管理

Person maggie = db.query(...).next();
Person kayla = db.query(...).next();
kayla.setAge(kayla.getAge() + 1); // 修改子物件
db.store(maggie); // 存儲根物件,級聯更新可達變更
db.commit();
  • 原理:db4o 掃描存儲物件圖,比對物件 ID,僅更新有變更的欄位。
  • 激活深度:若 kayla 未被激活 (深度不足),修改其欄位不會持久化。確保更新前物件圖已充分激活,或使用 db.ext().activate(obj, depth)。

刪除:級聯刪除的雙刃劍

db.delete(kayla); // 級聯刪除:從所有引用處移除
db.commit();

後果:bruce.children、maggie.children 中對應元素變為 null (或被移除,視 db4o 版本配置),導致集合出現「空洞」。

最佳實踐:軟刪除 (標記 deleted=true) + 定期清理,或在應用層手動維護雙向集合一致性後再 delete 根物件。

陣列 vs 集合:關鍵差異總結

特性陣列 (Address[])集合 (ArrayList<Person>)
查詢陣列本身不可直接查詢可作為獨立實體查詢 (但罕用)
元素獨立身份值物件通常無獨立 ID實體物件擁有獨立 ID,可被獨立查詢
長度固定/動態固定長度動態增減
建模適用場景固定槽位的值物件 (地址、電話)動態一對多實體關係 (子女、訂單項目)

結語

db4o 讓 Java 開發者以純物件思維處理多樣性關係:集合即關係,存儲即圖持久化,查詢即物件導航。核心關鍵在於:

  1. 理解可達性持久化邊界,單一 store(root) 足矣。
  2. 掌握激活深度與查詢/更新一致性的關係。
  3. 謹慎使用級聯刪除,優先考慮軟刪除或應用層關係維護。
  4. 集合元素為一級實體,可獨立查詢、跨關係共享,這是對象數據庫區別於 ORM 的核心優勢。

若專案需跨平台、嵌入式、零配置、原生物件圖持久化,db4o 仍是極具吸引力的選擇;若需複雜報表、SQL 生態整合,傳統 ORM (Hibernate/JPA) 更適合。

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