因無自動關聯加載/保存,**關係導航必須在代碼層顯式處理**,且 `IObject` 模式下**領域類不能持有其他領域類引用** (只能持有外鍵 ID)。
| 場景 | 策略 | 代價/收益 |
|---|---|---|
| 主表 + 細粒度從表 (如 User + Name) | 表合併:將 Name 字段併入 User 表 | 避免產生貧血細粒度對象、省去 CRUD 代碼、消除關聯麻煩 |
| 大表 + 大表 (如 Order + Payment) | 外鍵關聯:從表持有主表 ID (或雙向持有 ID) | 需手工管理關聯一致性、查詢時手工 Join 或兩次查詢 |
IObject 限制:不能在 `User` 中聲明 `private Name name;`,只能 `private Long nameId;`。
經典案例:`User` ↔ `Role`,中間表 `User_Role`。
| 策略 | 做法 | 優點 | 缺點 |
|---|---|---|---|
| 純 SQL 兩層嵌套查詢 | `UserUtil.getRoles()` 手寫 SQL:`SELECT * FROM Role WHERE id IN (SELECT role_id FROM User_Role WHERE user_id=?)` | 無額外對象、JDBC 風格熟悉 | 查詢次數多、代碼重複、維護難 |
| 中間表建對象 (推薦) | 創建 `UserRole` 對象映射 `User_Role` 表,冗余字段:`userName`、`roleName` | 單次查詢獲取豐富信息、模板渲染直接用 `$UserRole.userName`、避免多表 Join | 冗余數據需同步維護 (應用層保證) |
冗余字段原則:僅冗余「頻繁讀取、極少變更、業務關鍵」字段 (如名稱、編碼),避免大文本、頻繁變更字段。
// 保存/更新 (自動判斷主鍵是否為空)
object.save();
// 刪除
object.delete();
// 主鍵查詢
User user = (User) User.class.getObject(id);
// 條件查詢 (返回 List)
List users = User.query("WHERE username LIKE ?", "%john%");
// 分頁查詢
Page page = User.queryPage("WHERE 1=1", pageNo, pageSize);
// 批量操作
User.delete("WHERE status=?", "INACTIVE");
User.update("SET last_login=?", new Date(), "WHERE id=?", id);
| 項目特徵 | 是否適合 EasyDBO |
|---|---|
| 表結構簡單、關聯少、團隊追求極簡 | ✅ 非常適合 |
| 複雜領域模型、豐富關聯、需級聯持久化 | ❌ 不適合,選 Hibernate/JPA |
| 舊系統 JDBC 改造、想保留 SQL 控制權 | ✅ 平滑過渡 |
| 需要二級緩存、查詢緩存、延遲加載 | ❌ 無此類特性 |