Domain Object Model and Hibernate detached object
假定我現在正在設計一套圖書館自動化系統,我想設計為領域驅動模型(也就是非貧血模型),持久層的模型為hibernate O/R Mapping
http://www.martinfowler.com/bliki/AnemicDomainModel.html讓我們來關注系統中的三個類文件:LibraryUser , Borrow and Item
表關系如下:
LibraryUser --(1:M)--> Borrow <--(1:1)--> Item [<--(M:1)-- Book]
LibraryUser.java:
1 public class LibraryUser implements java.io.Serializable {
2
3 private Long id;
4 private Long version;
5 private String cardKey;
6 private String unifiedKey;
7 private Date admissionDate;
8 private Date expiryDate;
9 private Set borrows = new HashSet();
10 private Set reservations = new HashSet();
11 private Set libraryUserTypes = new HashSet();
12
..
13
14 // get , set
15
16 }
17 Borrow.java:
18 public class Borrow implements java.io.Serializable {
19
20 private Long id;
21 private Long version;
22 private Date borrowDate;
23 private Date dueDate;
24 private Date returnDate;
25 private Date reportlostDate;
26 private Short renewedNo;
27 private LibraryUserType libraryUserType;
28 private Item item;
29 private LibraryUser libraryUser;
30
..
31
32 // get,set
33
34 }
35 Item.java:
36 public class Item implements java.io.Serializable {
37
38 private Long id;
39 private Long version;
40 private String barcode;
41 private String shelfMark;
42 private Date lastCheckin;
43 private Set borrows = new HashSet();
44 private Book book;
45 private ItemDuration itemDuration;
46 private ItemStatus itemStatus;
47 private ItemType itemType;
48 private Location location;
49
..
50
51 // get,set
52
53 } 在三個類中現在僅有數據屬性,現在我想再加一些方法。因為是一個圖書管理系統,借書是一個常規動作,
所以第一步我想在LibraryUser類中加入borrow方法。如果我想領域驅動來設計的話應該如何放置borrow方法呢?
如果上述是正確的話,方法如下:
方法一.
LibraryUser.java,
1 public class LibraryUser implements java.io.Serializable {
2
3
..
4
5 public void borrow(Item item,LibraryUserType libraryUserType) {
6
7 Borrow borrow = new Borrow();
8 borrow.setLibraryUser(this);
9 borrow.setLibraryUserType(libraryUserType);
10 borrow.setItem(item);
11 borrow.setBorrowDate(new Date());
12 
13 // The code here suppose to check the this libraryUser can borrow the item or not
14 // l skip it for simple dicussion , let's assume that not checking is required. :)
15
16
17 this.getBorrows().add(borrow);
18 }
19
20 } 然后在我的controller中,我只是在borrow方法中傳入item,libraryUserType參數保存它
controllerA
1 libraryUser.borrow(item,libraryUserType);
2 getLibrary().storeLibraryUser(libraryUser);
這樣看起來較為常見,因為每一個libraryUser借書,所以borrow方法應當屬于libraryUser
但是如果我們要級聯保存liberaryUser(libraryUser是獨立的)的話,會導致會導致多次更新借書,除非你
在borrow.hbm.xml設置select-before-update="true",但是會導致一些性能損失。
Of course , we can do it another way , feed libraryUser, item , libraryUserType into borrow , and save borrow ,
當然我們可以將libraryUser, item , libraryUserType注入borrow中來達到同樣的效果
方法二、
1 Borrow borrow = new Borrow();
2 borrow.setLibraryUser(libraryUser);
3 borrow.setLibraryUserType(libraryUserType);
4 borrow.setItem(item);
5 borrow.setBorrowDate(new Date());
6 
7
8 getLibrary().storeBorrow(borrow); 這個方法對于關系型數據庫來說是非常常見的一種方法,保存一個borrow對象,
我們僅僅需要LIBRARY_USER_ID, ITEM_ID ,LIBRARY_USER_TYPE_ID , 當然還有DUE_DATE , ...等等
他只執行一句query.
insert into BORROWS (VERSION, BORROW_DATE, DUE_DATE, RETURN_DATE, REPORTLOST_DATE, RENEWED_NO, LIBRARY_USER_TYPE_ID, ITEM_ID, USER_ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
Q1. 方法2是否是一個貧血的領域模型呢?
Q2. 領域建摩的方法是什么,我是不是從一開始就錯了呢?
------------------reply----------------------
It wasnt clear from that what the relationship is between a borrow and a book.
從上述描述來看在borrow和book之間的關系不是很清晰。
第一個想法---封裝
First thought - encapsulation...
protected的item中除了簡單的屬性之外有沒有基于collection之類的get/set方法呢?
譬如,一個getBorrows()方法返回一個set類型,或者返回一個Collections.unmodifiableSet(borrows)
這樣的話,在沒有你的允許之下調用代碼不能修改你的對象內部狀態.
borrow方法的安置...
看起來將borrow方法放于LibraryUser中并不是最佳的位置。
你的領域內有一個書庫的概念嗎?很明顯你想知道一個User借什么書,但是我想你更想知道所有User在同時借閱books的數量。
在這種前提下我建議你創建一個BookRepository或者其他你想要的名稱。這個BookRepository總是在記錄borrow和你想要得到的用戶信息.
如果你讓repository來控制borrow,并不級聯User的borrows,那么你就可以避免上述討論的性能損失。
一個user的borrows將會被你在內存中/inverse mapping(如果你使用hibernate的話)管理。
你閱讀過<<Patterns of Enterprise Application Architecture>>或者<<Domain Driven Design>>嗎?你一定會喜歡的
posted on 2005-11-03 10:50
老妖 閱讀(1027)
評論(1) 編輯 收藏