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

開源物件資料庫 db4o 實戰:三種查詢方式 (QBE/SODA/NQ) 深度對比與最佳實踐

     編輯:Java 程式設計入門

db4o 簡介

db4o (database for objects) 是純 Java/.NET 的原生物件資料庫,無需 ORM 映射,直接持久化物件圖。核心優勢:零配置、ACID 事務、原生查詢 (Native Query) 提供 100% 型別安全與重構友善。本文涵蓋安裝、啟動模式、三大查詢 API 實戰與效能考量。

環境建置

  • 下載 db4o-5.5-java5.jar (JDK 5+) 或對應版本,單一 JAR 無第三方依賴。
  • 工具:ObjectManager (GUI 瀏覽 .yap 檔案)。
  • Maven:<dependency><groupId>com.db4o</groupId><artifactId>db4o</artifactId><version>8.0.184.15484</version></dependency> (新版群組 ID 變更)。

兩種運行模式

注意:ObjectContainer 非執行緒安全,多執行緒環境每執行緒一實例或使用連接池。

範例領域模型


package model;
import java.util.*;

public class Person {
    private int id;
    private String name;
    private String city;
    private List cars = new ArrayList<>();

    // getter/setter/addCar 略
}

public class Car {
    private int id;
    private String licensePlate;
    private Person owner; // 反向引用

    // getter/setter 略
}

儲存物件圖


ObjectContainer db = Db4oEmbedded.openFile("cars.yap");
try {
    Person p = new Person(); p.setId(1); p.setName("張三"); p.setCity("成都");
    Car c = new Car(); c.setId(1); c.setLicensePlate("川A00001");
    c.setOwner(p); p.addCar(c);
    db.store(p); // 遞迴持久化關聯物件
    db.commit();
} finally { db.close(); }

三種查詢方式實戰對比

1. QBE (Query By Example) — 最直觀、功能最受限


// 以原型物件為範本,非預設值欄位以 AND 組合
Car template = new Car();
template.setLicensePlate("川A00001");
List result = db.queryByExample(template); // 返回 List
for (Car car : result) {
    System.out.println("車主: " + car.getOwner().getName());
}
  • 優點:零學習曲線、程式碼極短。
  • 缺點:無法表達 OR/NOT/範圍/排序;基本型別預設值 (0、false、null) 無法作為查詢條件;依賴反射效能較差。

2. SODA (Simple Object Database Access) — 低階、動態組裝


Query q = db.query();
q.constrain(Car.class);
q.descend("licensePlate").constrain("川A00001");
q.descend("owner").descend("city").constrain("成都"); // 關聯查詢
q.orderDescending("id"); // 排序
List result = q.execute();
  • 優點:支援完整查詢運算子 (and/or/not/比較/排序/分頁);可動態組裝查詢 (如依使用者勾選條件);為 NQ 優化器的目標中介表示。
  • 缺點:字串欄位名稱無編譯期檢查、重構易斷;API 冗長。

3. NQ (Native Query) — 現代首選、100% 型別安全


List result = db.query(new Predicate() {
    @Override public boolean match(Car car) {
        return "川A00001".equals(car.getLicensePlate())
            && "成都".equals(car.getOwner().getCity());
    }
});
// 或 JDK 8 Lambda
List result = db.query(car -> "川A00001".equals(car.getLicensePlate())
                                 && "成都".equals(car.getOwner().getCity()));
  • 核心優勢:
    • 純 Java 語法,IDE 完整支援自動完成、重構、靜態分析。
    • 編譯期即發現拼字錯誤、型別不符。
    • 內部優化器嘗試轉換為 SODA 利用索引,若無法優化則退回實例化掃描 (需注意效能)。
  • 分頁實作:
    
    // 取得所有符合條件的 ID (不實例化完整物件)
    List all = db.query(car -> car.getOwner().getCity().equals("成都"));
    int pageSize = 20;
    for (int page = 0; page < (all.size() + pageSize - 1) / pageSize; page++) {
        List pageList = all.subList(page * pageSize, Math.min((page+1)*pageSize, all.size()));
        for (Car car : pageList) {
            System.out.println(car.getLicensePlate()); // 此時才觸發物件實例化
        }
    }
    

    db4o 僅在 query() 返回列表時載入內部 ID,實際物件在首次存取時才反序列化,避免記憶體爆炸。

效能優化關鍵

  1. 索引:ObjectContainer.ext().configure().objectClass(Car.class).objectField("licensePlate").indexed(true); 建立 B-Tree 索引,NQ/SODA 自動利用。
  2. 透明激活深度:activationDepth 控制關聯物件自動載入層級,避免一次載入整張物件圖。
  3. 查詢優化器:db4o 8.0+ 內建 NQ→SODA 優化器,複雜邏輯 (如集合操作、算術運算) 可能無法優化,建議簡化 Predicate 或改用 SODA。
  4. 物件身分與 UUID:內部 ID (長整數) 適合內部引用;跨資料庫同步需使用 UUID 欄位。

常見陷阱與對策

模式啟動方式適用場景
嵌入式 (單用戶)ObjectContainer db = Db4oEmbedded.openFile(config, "data.yap");桌面應用、嵌入式裝置、單元測試
客戶端/伺服器Server: ObjectServer server = Db4oClientServer.openServer(config, "data.yap", 8080); server.grantAccess("user","pwd");
Client: ObjectContainer db = Db4oClientServer.openClient(config, "host", 8080, "user", "pwd");
多行程/多機器共享資料、Java EE 環境

結語

db4o 以「物件即資料」哲學消除阻抗失配。實務建議:預設使用 NQ (Lambda) 享受型別安全與重構友善;動態查詢組裝用 SODA;原型快速驗證用 QBE。配合索引策略與激活深度控制,可在嵌入式/客戶端-伺服器雙模式下支撐中小型專案的高效開發。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
問題原因解決
修改物件後查詢不生效未呼叫 db.store(obj) 或 db.commit()寫入後必須 store+commit;或啟用 configuration.updateDepth
刪除後關聯物件殘留db4o 不自動級聯刪除手動遞迴刪除或使用 cascadeOnDelete 配置
多執行緒存取衝突ObjectContainer 非執行緒安全ThreadLocal 容器或連接池 (每執行緒一容器)
NQ 效能差優化器無法轉換,退回全表掃描加索引、簡化 Predicate、改用 SODA 指定索引路徑