Tin's Blog

You are coming a long way, baby~Thinking, feeling, memory...

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  58 随笔 :: 0 文章 :: 221 评论 :: 0 Trackbacks
内容太乱,如果懒得看请只看粗体部分就可以了
springside的一个特点就是manager继承自DAO,其实这是个名字上的问题。
Java EE一直强调分层架构,在Web部分比较典型的就是前端MVC、中间Business、后面持久化。而Manager对应business,持久化由于实现替换的需求一般使用DAO模式。
先分析一下在轻量化的Java EE下面他们存在的意义:
1、有的人说过在Web项目中Manager和DAO是同意的,尤其是在透明ORM存在下,DAO由于往往是CRUD的实现场所,而Manager却往往是薄薄的一层门面,很多人就在质疑两者的合并问题。可是robbin曾经进行过一个精辟的分析,虽然两者做的看起来差不多,可是两者的事务属性却不一样,Manager应该有清晰的事务界限,而DAO不应关心于此。也就是说Manager可能会将几个DAO方法组合调用,然后封装在一个事物中。这样说明确了两者的一个重要区别,我们也能体会在使用声明事务的时候有一个分明的事务界限是很有意义的,否则就有可能把Manager中的一个事物拆分,这样实际上就错误了。
2、有些人质疑透明ORM存在的情况下DAO存在的意义,因为透明ORM基本已经隔离了不同数据库的方言区别。这个也很简单,Rod大叔分析过。透明ORM存在的情况下DAO起到了隔离透明ORM与EJB或者JDBC实现的作用,这几种实现实际上是应该考虑到的。
3、还有一个问题,就是DAO是否应该隐藏透明ORM的API。因为前面说到了DAO起到隔离实现的作用,似乎应该隐藏特定API。可是某大叔也说过,完全隔离不可能,修改底层实现而不修改上层API也不划算(应该说往往费力不讨好),其实就是Rod大叔的思想,我们宁可提供各种support或者template,但是不强求抽象出各种实现。所以DAO的实现即使依赖于部分Hibernate API也不是错
上面纯属贫嘴,知道的朋友们不要嫌弃。
说说Springside的实现。
其实,实际上Springside使用的就是经典的GenericHibernateDAO+无Manager的实现。这么说在否定前面所说,不过其实这都是文字游戏:D
首先,对于Hibernate为主的实现下,DAO使用Generic是很方便的。Spring的hibernate template受累于向JDK1.4兼容,所以没有用generic,但是实际上DAO是generic的经典应用。在Hibernate网站上有过讨论。现在Springside使用的GenericHibernateDAO已经进化的非常先进了。
Springside实际上有Manager,我说没有其实是指它的Manager继承自DAO。看似乱伦,但实际上非常合理。前面说了Manager与DAO的很大区别在于事物范畴,使用继承后,两者之间就可以分离,可以通过Spring的AOP将事物属性配置在Manager上,也就解决了问题。这应该说也是template模式的标准应用。本来Manager就有很多方法可以通过模板实现,而DAO和Generic就很好地解决了他们之间的模板关系。
我们先看看具体的设计:
以CustomerManager为例,我们看看类签名:
CustomerManager extends BaseHibernateDao<Customer>
BaseHibernateDao<T> extends AbstractHibernateDao<T>
AbstractHibernateDao<T> extends HibernateDaoSupport

三层结构:
第一层AbstractHibernateDao继承自大家都熟悉的Spring的HibernateDaoSupport,这一层的主要作用是扩展Generic,这样一方面减少了强行类型转换的啰嗦,一方面使DoaminClass的信息通过Generic继承透明声明。这一层还有一个作用,就是说不管你是否使用Generic,你的应用程序最好也在这里增加一层继承,作用是在需要的时候你可以在这里扩展DAO模版:D
第二层是BaseHibernateDao。这个其实是springside很自豪的一个地方,可以理解,因为这里真的花了很多的代码,而且相当精妙。
不卖官子,其实这里主要给DAO扩展了分页支持,这显然是异常重要的,大家google一下就知道分页在Web应用中的重要性了,基本上你看一个Java Web Framework都会看到它对自己分页特性的支持方式介绍,或者说分页的实现风格已经是Java Web Framework实现优劣的一个标准了。应该说,springsdie的分页实现来自javaeye上的一个经典的讨论,robbin等牛在里面仔细讨论了用DetachedCriteria实现分页查询,后面引出bug,然后解决,希望没看过的朋友都看看。(应用Hibernate3的DetachedCriteria实现分页查询|http://forum.javaeye.com/viewtopic.php?t=14657&postdays=0&postorder=asc&start=0)
springside的实现是集大成者,考虑到了Criteria(不仅是DetachedCriteria)、HQL、collection.size()几种不同实现,也考虑到了使用Criteria的时候Order造成的问题(这个在我的Blog中给DetachedCriteria擦屁股那个里面讨论过)。
第三层就是具体的Manager,它是用Generic继承传递了DoaminModel的类信息。由于大部分CRUD已经在DAO里面实现了,所以Manager只需要实现一些需要特殊实现的method的就可以了,简单的应用中Manager里面经常是空空如也。

其中,BaseHibernateDao的实现相对复杂,主要因为里面包装了分页实现。大家可以具体看看CriteriaPage和HqlPage两个类,这是精妙所在。但是在这一层还有个CriteriaSetup是个比较奇怪的东西,一开始没太看明白是做什么用的。后来问了百衣,他说这是为了解决search问题提供的,从jsp传递过来的东西在Controller层可以通过util(这里springside很CoC,它把search_开头的东西自动作为“=”的查询条件传给Manager,但目前的缺陷在于只能默认处理“=”,其它方式需要扩展)处理查询条件传给Manager,但是这个东西设计得有点怪,白衣也对它不满意,说在Springside 2.0里面要重构掉,但还没有什么好的想法,大家又建议可以提给他。
我认为传递查询信息大概需要这样的设计:
1、在Controller里面不暴露hibernate API,但是能够顺利将参数传递到Manager。
2、Manager直接传递,或者将这些参数转换为Hibernate API后再传递,因为这正是manager需要负责的商业逻辑之一。
3、DAO里面最好不要做那么多转换,毕竟它是持久层。
当然,目前符合这个要求,只是限定于Map是二元容器,不能存3元的查询条件(key、value、type)。所以可能下一步会补足。
分析到这里,springside的DAO的结构大概就是这样的。
感觉这和我们Team上个项目的结构很象(不好意思,没说有springside那么好),有一点区别。
由于Manager继承自DAO,我们让DAO多了很多方法,主要就是想提供方便。尤其是
<T> T loadById(Class<T> persistenceClass, Serializable id);
<T> T loadByProperty(Class<T> persistenceClass, String propertyName, Object value);
<T> List<T>listAll(Class<T> persistenceClass);
<T> List<T>listByProperty(Class<T> persistenceClass, String propertyName, Object value);
<T> List<T>listAllOrderBy(Class<T> persistenceClas, boolean isAsc, String orderByPropertyName);
可是springside并没有提供这样的东西,有点遗憾。
这些东西经常用到,如果使用了会减少了很多时候遇到的Manager里面注入其他Domain的DAO,却只是为了load或者listAll的问题(同时用generic):D

今天有点别的事,先说到这里,好好想想,看有什么问题过两天在说说。这Blog太流水账,太空洞,大家见谅。
posted on 2006-09-05 21:52 Tin 阅读(3480) 评论(3)  编辑  收藏 所属分类: Other Project

评论

# re: 看看Springside的DAO和Manager 2006-09-05 21:59 dukerr
缺乏要点 ,乱!
大家的时间都很宝贵!  回复  更多评论
  

# re: 看看Springside的DAO和Manager 2006-09-05 22:30 Tin
楼上朋友,不好意思,我修改了下,如果赏光,可以只看促体部分:D
希望不要浪费大家过多时间。  回复  更多评论
  

# re: 看看Springside的DAO和Manager 2006-09-05 22:49 江南白衣
“如果使用了会减少了很多时候遇到的Manager里面注入其他Domain的DAO,却只是为了load或者listAll的问题(同时用generic):D”

好,SS2.0会加入他们。不过listAll的使用要注意,看是否默认就要用带状态过滤的list函数。  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: