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

db4o 物件資料庫實戰:陣列與集合的持久化與關聯管理

     編輯:Java 相關知識

前言:模擬真實世界的多重關聯

db4o 物件資料庫的優勢在於能直接持久化物件圖,無需 ORM 映射。本文透過擴充 Person 類別,示範如何處理陣列(固定數量地址)與集合(動態子女清單)的持久化、查詢與關聯維護。

領域模型設計

Address 值物件

public class Address {
    private String street, city, state, zip;
    // 建構子、getter/setter、equals/hashCode/toString 略
}

Person 實體:包含陣列與集合

public class Person {
    private String firstName, lastName;
    private Gender gender;
    private int age;
    private Mood mood;
    private Person spouse;
    private Address[] addresses = new Address[3];  // 固定三個地址:住家、公司、渡假屋
    private List<Person> children = new ArrayList<>();  // 動態子女清單
    private Person mother, father;  // 雙向父母關聯

    // 業務方法:生小孩(含生理/倫理規則驗證)
    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 = spouse; child.mother = this;
        children.add(child); spouse.children.add(child);
        return child;
    }
    // getter/setter、equals/toString 略
}

測試資料建立與持久化

@Before
public void prepareDatabase() {
    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);
    bruce.setHomeAddress(new Address("5 Maple Drive", "Austin", "TX", "12345"));
    bruce.setWorkAddress(new Address("5 Maple Drive", "Austin", "TX", "12345"));
    bruce.setVacationAddress(new Address("10 Wanahokalugi Way", "Oahu", "HA", "11223"));
    Person kayla = maggie.haveBaby("Kayla", Gender.FEMALE); kayla.setAge(8);
    Person julia = maggie.haveBaby("Julia", Gender.FEMALE); julia.setAge(6);
    db.store(bruce);  // 遞迴持久化整個物件圖
    db.commit();
}

查詢驗證:關聯完整性自動維護

db4o 自動維護物件參考完整性,跨查詢取得的物件仍保持關聯:

// 查詢地址
List<Person> maleTates = db.query(new Predicate<Person>() {
    public boolean match(Person c) { return "Tate".equals(c.getLastName()) && c.getGender()==Gender.MALE; }
});
assertTrue(bruce.getHomeAddress().equals(new Address("5 Maple Drive", "Austin", "TX", "12345")));

// 查詢子女
for (Person child : bruce.getChildren()) { ... }  // 正確取得 Kayla、Julia

// 查詢所有女性
List<Person> girls = db.query(new Predicate<Person>() {
    public boolean match(Person c) { return c.getGender()==Gender.FEMALE; }
});  // 包含 Maggie、Kayla、Julia

// 跨查詢驗證雙向關聯
Person maggie = db.get(new Person("Maggie", "Tate", Gender.FEMALE, 0, null)).next();
Person julia = db.get(new Person("Julia", "Tate", Gender.FEMALE, 0, null)).next();
assertTrue(julia.getMother() == maggie);  // 同一物件實例

更新與刪除:級聯操作注意事項

// 更新:修改子女年齡後存儲父母即可級聯更新
kayla.setAge(kayla.getAge() + 1);
db.store(maggie);
db.commit();
// 重新開啟資料庫驗證
db = Db4o.openFile("persons.data");
assertEquals(kaylasNewAge, db.get(...).next().getAge());

// 刪除:級聯刪除會移除所有參考,導致父母的 children 清單出現 null
// 需謹慎設計刪除策略,避免殘留無效參考

關鍵心得

  • 陣列不可直接查詢,集合可作為一級物件被查詢
  • 物件圖遞迴持久化:只需存儲根物件
  • 關聯完整性由 db4o 自動維護(啟用深度足夠時)
  • 建模階段解決 null 問題,而非操作階段
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved