SpringSide是一个fantasy的好项目,可惜驽钝,没能加入其中,有时会看看它的代码,吸取一些养分。
http://www.springside.org.cn/
今天先看看Springside的bookstore的domain设计,这不是springside的重点,先看看。
从hbm看起,在springside-bookstore/src/org.springside.bookstore.commons.domain.hbm下面放着这些hbm。
在Order.hbm.xml里面可以看到一个list映射。list映射可以按照顺序持久化one-to-many关系。使用了<composite-element>映射后OrderItem就没有单独的class声明了,完全以一种组件的形式被映射到Order里面。
有序的List映射是很方便的,这样就可以通过List的set(int, Object)来改变OrderItem的顺序,这个需求是经常被提起的。
Order.java里面可以看到在价格计算上使用了Rule,Rule是用String纪录的rule id,我记得springside团队试验性的使用了Drools,具体在进步研究后分析。
Order实现了AclDomainAware接口,可见是用ACL进行了访问控制。没有继承自统一的DomainObject基类,这个不知从何考虑,感觉Domain继承自统一基类在框架很多地方都可以得到便利。实现接口在这里应该作为一种签名标示,作为某些环节或者拦截器使用。SpringSide这里应该是用的是Acegi,可以看到这个是差沙同学实现的。
Order这部分就没有什么其它特别之处了,是比较典型的pojo,贫血模型:D。在这里没有看到全功能DomainModel的影子。此时修改Order里面的orderItems就需要手动替换,addProduct的功能都不在这里,的确有点不爽。
BTW:在Order.hbm.xml的配置里面可以看到上面有一行<import class="org.springside.bookstore.commons.domain.OrderItem"/>,不知道起什么作用,希望了解的朋友指点。
在Product.hbm.xml里面有一个继承映射:“每个类分层结构一张表(Table per class hierarchy)”的形式。
再进到Product.java里面,它实现了HistorizableEntity接口,而前者又继承自AuditableEntity。
从里面的注释上看HistorizableEntity作为Hibernate Event Listener的记号,对此接口的领域对象自动保存修改纪录,这个我找到代码在org.springside.core.commons.support.audit.HistoryEventListener里面。这个东西被配置到session上。从代码上看,这个东西用来记录这个商品的LifeCycle,不过代码还没有完成,不知道calvin同学会用什么方法得到user等信息(Hibernate Listener是单例,不能有状态信息)。这种方法在RoR里面有个_at和_on的后缀,可以自动完成修改时间等信息的持久化,不知道此处是否是要实现类似的功能。
Product里面有个@SearchableId、@SearchableProperty、@SearchableComponent的注释,这是compass的注释,这种暴露属性提供搜索的配置方式非常舒服,是对pojo进行搜索的好例子。compass对Lucene的包装是不错的,这里好像是hellboys同学写的,有时间深入看一下。
限制描述字段的功能放到了pojo里面,这个方法很不错,大家也都在用。
Product的toString方法使用的是ToStringBuilder.reflectionToString,这个不知大家是否常用,不过这个东西大家要主要。比如在Domain公用基类中就不要用,否则它会对所有lazy load的属性有毁灭性打击:D。Springside没有使用这种结构,当然没关系。
Book是Product的子类,继承是OO特性,这里显然考虑周到,Springside也就不是仅能卖书的应用了:D。equals、hashCode方法都出现了重复。不过,重构强调任何形式的重复都是邪恶的,RoR的Hansson坚信之,所以有了CoC概念。
不过这里产生一个问题,我实现的一些应用中发现对于Hibernate的继承,类型转换是个令人头疼的问题,相当不舒服,因为descrimitor对于你是不可见的,你很难在保留id的情况下强行转换一个子类到另一个子类。这点很不灵活,不知大家有什么好办法?
Custemer、Category是单纯的Pojo。Category没有实现层次,这点比较失望,感觉应该做一个树形结构的显示管理的demo。
下面的部分,我会继续分析:D