個人BO之導航屬性

個人BO
1-個人BO之強類型
2-個人BO之數據保護
3-個人BO之狀態控制
4-個人BO之導航屬性html

數據須要導航

數據之間廣泛存在關係,作業務處理時每每也是按照關係在數據之間查詢和處理。業務處理可看做是各類檢查和計算後,保存結果。而檢查和計算每每意味着要查數據A,以及數據A相關的數據B,數據B相關的數據C……。java

BO 與數據表相對應。一個 BO 類對應一個數據表,一個 BO 對象對應數據表中的一條記錄。表間的關係,也是 BO 間的關係。典型的是一對多關係。好比 「買家-訂單-訂單明細」三者的關係是:一個買家能夠擁有多個訂單,一個訂單對應多個訂單明細;反過來,一個訂單明細對應一個訂單,一個訂單對應一個買家。訂單是買家的子對象,買家是訂單的父對象。數據庫

當獲得一個訂單 BO 時,但願能夠經過它的屬性獲得它的明細,明細是一個 BO 集合,但願能夠經過它的另外一個屬性獲得它的買家 BO。同理,當獲得一個訂單明細 BO,但願能夠經過它的一個屬性獲得它的訂單 BO。緩存

經過 BO 的屬性獲取到另外一個 BO 或 BO 的集合,這種屬性叫作 BO 的導航屬性。安全

對null值的處理

當父對象可能爲null時,導航到父對象的屬性有兩個,一個是Xxx,另外一個是XxxOrNull。好比一個學生通常是對應一個班級,但若是業務邏輯容許新生報到時暫未分配到班級,學生的班級屬性就可能爲null。爲了準確地處理null值的問題,學生的班級對應兩個屬性:ClassClassOrNull。並規定,Class這個屬性不返回null,學生當前沒有對應班級時,則拋異常,若是但願返回null而非拋異常,則使用ClassOrNull。當父對象不容許爲null時,則不提供XxxOrNull屬性。ide

子對象通常表現爲父對象的一個集合屬性,若一個對象的子對象數量爲零,則規定返回空(Empty)集合,而不是nullthis

class 班級Bo extends BoBase {
    public List<學生Bo> get學生List() {
        Long id = this.getId();
        return boProvider.list學生By班級Id(id); // 見說明1
    }
}

class 學生Bo extends BoBase {
    public 班級Bo get班級() {
        Long 班級Id = this.get班級Id();
        return boProvider.get班級(班級Id);
    }
    public 班級Bo get班級OrNull() {
        if (this.get班級Id() == null)
            return null;
        return this.get班級();  // 見說明2
    }
}

說明:設計

  1. boProviderBoBase的屬性,一切的 BO 對象都由boProvider產生。
  2. 若是班級Id不是null,卻在數據庫中找不到該班級數據,則仍是會拋異常,也應該拋異常。
  3. 爲了便於說明且不影響道理的表達,這裏使用了中文命名,實際項目中並不是如此。

優勢

  • 導航屬性讓使用者方便地獲得 BO 對象的相關對象,屏蔽了內部關係的細節,使用方便。
  • 導航屬性包含了找不到時返回null仍是拋異常的邏輯,避免了處處編寫重複的代碼,減小了對null值的處理不當致使空引用異常的風險。
  • 效果:只要獲得一個 BO 對象,就能夠獲得與它相關的所有對象,使業務邏輯代碼簡潔、安全、靈活。

展望

目前的導航屬性是隻讀的,這點不夠面向對象(OO),只是由於實現起來簡單。將來如有須要,能夠提供修改導航屬性同時修改關係的功能,用起來更加OO,可能有一些複雜的技術細節問題要解決。3d

目前經過導航屬性獲取(BO)對象,每次都從數據庫裝載,必定機率下會產生多餘的查詢。解決方法是在內存中統一緩存,經過ID判斷若內存已有則不從數據庫中取。這個方案一方面會增長一點內存開銷,同時爲了知足「就算內存中有,也要從數據庫裝載」的需求,須要設計複雜一點的機制。還須要解決前面的業務修改了的對象,後面的業務(同一個請求)獲取是否應該獲取修改後的這個對象版本的問題,我目前以爲應該獲取修改後的版本,而不是數據庫中那個。不管獲取到的是哪一個版本,會不會在業務處理上形成Bug,有待進一步研究。code

系列導航

1-個人BO之強類型
2-個人BO之數據保護
3-個人BO之狀態控制 4-個人BO之導航屬性

相關文章
相關標籤/搜索