2015-07-10 43 views
2

將DAO的某些部分委託給另一個DAO會更好嗎,以便它更具可讀性和緊湊性?以及更少的重複代碼?數據訪問對象(DAO)是否應將其委託給其他DAO以提高可讀性?

class StudentDAOImpl implements StudentDAO { 
    public Student findById(int studentId) { 
     // some code here to get student 
    } 
} 

class SemesterEnrollmentImpl implements SemesterEnrollmentDAO { 
    public SemesterEnrollment findSemesterEnrollmentByStudent(int studentId) { 
     // delegating finding of student to StudentDAO 
     StudentDAO studentDao = new StudentDaoImpl(); 
     Student student = studentDAO.findById(studentId); 

     // code to get SemesterEnrollment using student instance 
    } 
} 

因爲我讀到的DAO應:

  • 的N + 1個問題。
  • 最小化SQL調用次數。
  • DAO不應委託給其他DAO。

這是否意味着我必須在每個DAO中重複相同的過程,而不是委託它,因此它將獨立於其他DAO?

回答

5

一個常見的事情是使用服務來調用不同的daos需要注入數據。在這種情況下,這似乎更合乎邏輯,因爲它實際上是業務邏輯,而且在您的數據庫層中儘可能少地使用這個數據庫

+0

加上我的DAO,DAO應該可以在各種用例之間重複使用,服務方法應該實現個別的細節級用例。 –

0

作爲一個經驗法則,DAO應該關心檢索/持久化數據所以任何業務邏輯或數據轉換最終都駐留在單獨的業務層中。在您提供的示例中,可以詢問如果由於根本沒有數據而導致給StudentDAO的呼叫失敗會發生什麼情況。這是服務層解決的那種問題。 在你的例子中,EnrollmentDAO可以變成EnrollmentService。

1

在您的示例中,主要問題在於您正在使用SemesterEnrollmentDAO搜索另一個實體。

你是否絕對需要檢索Student entitiy檢索SemesterEnrollment稍後?

如果您的實體之間的關係設計得很好,您可以使用studentId查詢SemesterEnrollment,而不必先檢索Student實體。

Query query = em.createQuery("SELECT e FROM SemesterEnrollment e JOIN e.student s " 
          + "WHERE s.studentId = :studentId"); 

這樣,你同時避免,委託和1層+ N的問題,如果你真的需要檢索什麼是SemesterEnrollment實體,如宜SemesterEnrollmentDAO

2

短的答案:否

的DAO可以稱之爲Table Module根據所述圖案限定於每類中的一個表

甲表模塊組織域邏輯與每個表一類在DATA-的基礎上,和一類的單個實例包含將所述數據起作用

然而的各種程序,這些可通過門面或Transaction Script包裹管理相互作用b在多個Table Modules之間。

事務腳本主要將所有這些邏輯組織爲單個過程,直接調用數據庫或通過瘦數據庫包裝器進行調用。每個事務都有自己的事務腳本,儘管常見的子任務可以分解爲子過程。

1

你知道的經驗法則,但沒有人正在解決原因。

DAO的作用是包含一組CRUD函數。每種方法都是針對事務性數據存儲(通常是數據庫)的一些操作。如果您將DAO呼叫鏈接在一起,則最終會一起鏈接交易。對於READS來說這不是什麼大問題;但是當你進入WRITES時,它會變得混亂。

例如,您有一個複合EnrollmentRecord對象。它包含StudentRecord,學生註冊的每個班級的SectionRecords,以及每個SectionRecord鏈接到一個ClassRecord。如果你調用createEnrollement(EnrollmentRecord),它也可以鏈接到EnrollmentRecord中包含其他對象。

如果您可以創建StudentRecord,但是某些SectionRecords或ClassRecords失敗會發生什麼?做回滾?你是否離開了學生,但是刪除了所有已註冊的課程?如果一個入學班失敗了,你會把他們全部推回去嗎?

一旦你開始協調交易,你現在在業務邏輯混合。業務規則將隨着時間和情況而改變;但入學,學生,科室和班級的基本CRUD不會。

使用Service對象來聚合DAO。組合數據對象應該由一個服務管理,該服務協調所有對DAO的調用(事件對多個DAO的多次調用!)這允許您將業務/事務邏輯從CRUD邏輯中分離出來,並保持每一層模塊化並可重用。

使用服務層的另一個重要原因是實體模型通常是雙向的。你可以加載一個學生,然後獲取他們所有的課程。你可以上課並加載所有的學生。隨着對象模型的增長,您將很容易獲得循環關係。

例如,您擁有objectA,其中包含objectB的集合。你的loadA方法調用loadB。

未來有人添加擴展loadB委託給LoadC。後來,有人說如果我能加載'C'並知道它連接到哪個'A'將會很好。因此,它們將loadC擴展爲委託給返回'A'對象的loadA。現在整個事情都爆炸了,沒有追蹤整個循環路徑就不明顯。

使用服務層來協調複合對象。將組合邏輯與CRUD邏輯分離,可以更輕鬆地避免循環引用和管理複雜的對象圖。

所以DAO調用DAO本身並不是邪惡的;但是,這種簡捷方式很容易導致處理CRUD,業務/事務邏輯和複雜對象圖規則的巨大DAO方法。從服務中清除DAO有助於防止這種情況發生。

相關問題