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
老妖 阅读(1022)
评论(1) 编辑 收藏