关于spring forum 的domain object 的第二篇讨论

关于spring forum 的domain object 的第二篇讨论
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>>吗?你一定会喜欢的

你可能感兴趣的:(关于spring forum 的domain object 的第二篇讨论)