內(nèi)容太亂,如果懶得看請(qǐng)只看粗體部分就可以了
springside的一個(gè)特點(diǎn)就是manager繼承自DAO,其實(shí)這是個(gè)名字上的問(wèn)題。
Java EE一直強(qiáng)調(diào)分層架構(gòu),在Web部分比較典型的就是前端MVC、中間Business、后面持久化。而Manager對(duì)應(yīng)business,持久化由于實(shí)現(xiàn)替換的需求一般使用DAO模式。
先分析一下在輕量化的Java EE下面他們存在的意義:
1、有的人說(shuō)過(guò)在Web項(xiàng)目中Manager和DAO是同意的,尤其是在透明ORM存在下,DAO由于往往是CRUD的實(shí)現(xiàn)場(chǎng)所,而Manager卻往往是薄薄的一層門面,很多人就在質(zhì)疑兩者的合并問(wèn)題。可是robbin曾經(jīng)進(jìn)行過(guò)一個(gè)精辟的分析,雖然兩者做的看起來(lái)差不多,可是兩者的事務(wù)屬性卻不一樣,Manager應(yīng)該有清晰的事務(wù)界限,而DAO不應(yīng)關(guān)心于此。也就是說(shuō)Manager可能會(huì)將幾個(gè)DAO方法組合調(diào)用,然后封裝在一個(gè)事物中。這樣說(shuō)明確了兩者的一個(gè)重要區(qū)別,我們也能體會(huì)在使用聲明事務(wù)的時(shí)候有一個(gè)分明的事務(wù)界限是很有意義的,否則就有可能把Manager中的一個(gè)事物拆分,這樣實(shí)際上就錯(cuò)誤了。
2、有些人質(zhì)疑透明ORM存在的情況下DAO存在的意義,因?yàn)橥该鱋RM基本已經(jīng)隔離了不同數(shù)據(jù)庫(kù)的方言區(qū)別。這個(gè)也很簡(jiǎn)單,Rod大叔分析過(guò)。透明ORM存在的情況下DAO起到了隔離透明ORM與EJB或者JDBC實(shí)現(xiàn)的作用,這幾種實(shí)現(xiàn)實(shí)際上是應(yīng)該考慮到的。
3、還有一個(gè)問(wèn)題,就是DAO是否應(yīng)該隱藏透明ORM的API。因?yàn)榍懊嬲f(shuō)到了DAO起到隔離實(shí)現(xiàn)的作用,似乎應(yīng)該隱藏特定API。可是某大叔也說(shuō)過(guò),完全隔離不可能,修改底層實(shí)現(xiàn)而不修改上層API也不劃算(應(yīng)該說(shuō)往往費(fèi)力不討好),其實(shí)就是Rod大叔的思想,我們寧可提供各種support或者template,但是不強(qiáng)求抽象出各種實(shí)現(xiàn)。所以DAO的實(shí)現(xiàn)即使依賴于部分Hibernate API也不是錯(cuò)。
上面純屬貧嘴,知道的朋友們不要嫌棄。
說(shuō)說(shuō)Springside的實(shí)現(xiàn)。
其實(shí),實(shí)際上Springside使用的就是經(jīng)典的GenericHibernateDAO+無(wú)Manager的實(shí)現(xiàn)。這么說(shuō)在否定前面所說(shuō),不過(guò)其實(shí)這都是文字游戲:D
首先,對(duì)于Hibernate為主的實(shí)現(xiàn)下,DAO使用Generic是很方便的。Spring的hibernate template受累于向JDK1.4兼容,所以沒(méi)有用generic,但是實(shí)際上DAO是generic的經(jīng)典應(yīng)用。在Hibernate網(wǎng)站上有過(guò)討論。現(xiàn)在Springside使用的GenericHibernateDAO已經(jīng)進(jìn)化的非常先進(jìn)了。
Springside實(shí)際上有Manager,我說(shuō)沒(méi)有其實(shí)是指它的Manager繼承自DAO。看似亂倫,但實(shí)際上非常合理。前面說(shuō)了Manager與DAO的很大區(qū)別在于事物范疇,使用繼承后,兩者之間就可以分離,可以通過(guò)Spring的AOP將事物屬性配置在Manager上,也就解決了問(wèn)題。這應(yīng)該說(shuō)也是template模式的標(biāo)準(zhǔn)應(yīng)用。本來(lái)Manager就有很多方法可以通過(guò)模板實(shí)現(xiàn),而DAO和Generic就很好地解決了他們之間的模板關(guān)系。
我們先看看具體的設(shè)計(jì):
以CustomerManager為例,我們看看類簽名:
CustomerManager extends BaseHibernateDao<Customer>
BaseHibernateDao<T> extends AbstractHibernateDao<T>
AbstractHibernateDao<T> extends HibernateDaoSupport
三層結(jié)構(gòu):
第一層AbstractHibernateDao繼承自大家都熟悉的Spring的HibernateDaoSupport,這一層的主要作用是擴(kuò)展Generic,這樣一方面減少了強(qiáng)行類型轉(zhuǎn)換的啰嗦,一方面使DoaminClass的信息通過(guò)Generic繼承透明聲明。這一層還有一個(gè)作用,就是說(shuō)不管你是否使用Generic,你的應(yīng)用程序最好也在這里增加一層繼承,作用是在需要的時(shí)候你可以在這里擴(kuò)展DAO模版:D
第二層是BaseHibernateDao。這個(gè)其實(shí)是springside很自豪的一個(gè)地方,可以理解,因?yàn)檫@里真的花了很多的代碼,而且相當(dāng)精妙。不賣官子,其實(shí)這里主要給DAO擴(kuò)展了分頁(yè)支持,這顯然是異常重要的,大家google一下就知道分頁(yè)在Web應(yīng)用中的重要性了,基本上你看一個(gè)Java Web Framework都會(huì)看到它對(duì)自己分頁(yè)特性的支持方式介紹,或者說(shuō)分頁(yè)的實(shí)現(xiàn)風(fēng)格已經(jīng)是Java Web Framework實(shí)現(xiàn)優(yōu)劣的一個(gè)標(biāo)準(zhǔn)了。應(yīng)該說(shuō),springsdie的分頁(yè)實(shí)現(xiàn)來(lái)自javaeye上的一個(gè)經(jīng)典的討論,robbin等牛在里面仔細(xì)討論了用DetachedCriteria實(shí)現(xiàn)分頁(yè)查詢,后面引出bug,然后解決,希望沒(méi)看過(guò)的朋友都看看。(應(yīng)用Hibernate3的DetachedCriteria實(shí)現(xiàn)分頁(yè)查詢|http://forum.javaeye.com/viewtopic.php?t=14657&postdays=0&postorder=asc&start=0)
springside的實(shí)現(xiàn)是集大成者,考慮到了Criteria(不僅是DetachedCriteria)、HQL、collection.size()幾種不同實(shí)現(xiàn),也考慮到了使用Criteria的時(shí)候Order造成的問(wèn)題(這個(gè)在我的Blog中給DetachedCriteria擦屁股那個(gè)里面討論過(guò))。
第三層就是具體的Manager,它是用Generic繼承傳遞了DoaminModel的類信息。由于大部分CRUD已經(jīng)在DAO里面實(shí)現(xiàn)了,所以Manager只需要實(shí)現(xiàn)一些需要特殊實(shí)現(xiàn)的method的就可以了,簡(jiǎn)單的應(yīng)用中Manager里面經(jīng)常是空空如也。
其中,BaseHibernateDao的實(shí)現(xiàn)相對(duì)復(fù)雜,主要因?yàn)槔锩姘b了分頁(yè)實(shí)現(xiàn)。大家可以具體看看CriteriaPage和HqlPage兩個(gè)類,這是精妙所在。但是在這一層還有個(gè)CriteriaSetup是個(gè)比較奇怪的東西,一開(kāi)始沒(méi)太看明白是做什么用的。后來(lái)問(wèn)了百衣,他說(shuō)這是為了解決search問(wèn)題提供的,從jsp傳遞過(guò)來(lái)的東西在Controller層可以通過(guò)util(這里springside很CoC,它把search_開(kāi)頭的東西自動(dòng)作為“=”的查詢條件傳給Manager,但目前的缺陷在于只能默認(rèn)處理“=”,其它方式需要擴(kuò)展)處理查詢條件傳給Manager,但是這個(gè)東西設(shè)計(jì)得有點(diǎn)怪,白衣也對(duì)它不滿意,說(shuō)在Springside 2.0里面要重構(gòu)掉,但還沒(méi)有什么好的想法,大家又建議可以提給他。
我認(rèn)為傳遞查詢信息大概需要這樣的設(shè)計(jì):
1、在Controller里面不暴露hibernate API,但是能夠順利將參數(shù)傳遞到Manager。
2、Manager直接傳遞,或者將這些參數(shù)轉(zhuǎn)換為Hibernate API后再傳遞,因?yàn)檫@正是manager需要負(fù)責(zé)的商業(yè)邏輯之一。
3、DAO里面最好不要做那么多轉(zhuǎn)換,畢竟它是持久層。
當(dāng)然,目前符合這個(gè)要求,只是限定于Map是二元容器,不能存3元的查詢條件(key、value、type)。所以可能下一步會(huì)補(bǔ)足。
分析到這里,springside的DAO的結(jié)構(gòu)大概就是這樣的。
感覺(jué)這和我們Team上個(gè)項(xiàng)目的結(jié)構(gòu)很象(不好意思,沒(méi)說(shuō)有springside那么好),有一點(diǎn)區(qū)別。
由于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并沒(méi)有提供這樣的東西,有點(diǎn)遺憾。
這些東西經(jīng)常用到,如果使用了會(huì)減少了很多時(shí)候遇到的Manager里面注入其他Domain的DAO,卻只是為了load或者listAll的問(wèn)題(同時(shí)用generic):D
今天有點(diǎn)別的事,先說(shuō)到這里,好好想想,看有什么問(wèn)題過(guò)兩天在說(shuō)說(shuō)。這Blog太流水賬,太空洞,大家見(jiàn)諒。

springside的一個(gè)特點(diǎn)就是manager繼承自DAO,其實(shí)這是個(gè)名字上的問(wèn)題。
Java EE一直強(qiáng)調(diào)分層架構(gòu),在Web部分比較典型的就是前端MVC、中間Business、后面持久化。而Manager對(duì)應(yīng)business,持久化由于實(shí)現(xiàn)替換的需求一般使用DAO模式。
先分析一下在輕量化的Java EE下面他們存在的意義:
1、有的人說(shuō)過(guò)在Web項(xiàng)目中Manager和DAO是同意的,尤其是在透明ORM存在下,DAO由于往往是CRUD的實(shí)現(xiàn)場(chǎng)所,而Manager卻往往是薄薄的一層門面,很多人就在質(zhì)疑兩者的合并問(wèn)題。可是robbin曾經(jīng)進(jìn)行過(guò)一個(gè)精辟的分析,雖然兩者做的看起來(lái)差不多,可是兩者的事務(wù)屬性卻不一樣,Manager應(yīng)該有清晰的事務(wù)界限,而DAO不應(yīng)關(guān)心于此。也就是說(shuō)Manager可能會(huì)將幾個(gè)DAO方法組合調(diào)用,然后封裝在一個(gè)事物中。這樣說(shuō)明確了兩者的一個(gè)重要區(qū)別,我們也能體會(huì)在使用聲明事務(wù)的時(shí)候有一個(gè)分明的事務(wù)界限是很有意義的,否則就有可能把Manager中的一個(gè)事物拆分,這樣實(shí)際上就錯(cuò)誤了。
2、有些人質(zhì)疑透明ORM存在的情況下DAO存在的意義,因?yàn)橥该鱋RM基本已經(jīng)隔離了不同數(shù)據(jù)庫(kù)的方言區(qū)別。這個(gè)也很簡(jiǎn)單,Rod大叔分析過(guò)。透明ORM存在的情況下DAO起到了隔離透明ORM與EJB或者JDBC實(shí)現(xiàn)的作用,這幾種實(shí)現(xiàn)實(shí)際上是應(yīng)該考慮到的。
3、還有一個(gè)問(wèn)題,就是DAO是否應(yīng)該隱藏透明ORM的API。因?yàn)榍懊嬲f(shuō)到了DAO起到隔離實(shí)現(xiàn)的作用,似乎應(yīng)該隱藏特定API。可是某大叔也說(shuō)過(guò),完全隔離不可能,修改底層實(shí)現(xiàn)而不修改上層API也不劃算(應(yīng)該說(shuō)往往費(fèi)力不討好),其實(shí)就是Rod大叔的思想,我們寧可提供各種support或者template,但是不強(qiáng)求抽象出各種實(shí)現(xiàn)。所以DAO的實(shí)現(xiàn)即使依賴于部分Hibernate API也不是錯(cuò)。
上面純屬貧嘴,知道的朋友們不要嫌棄。
說(shuō)說(shuō)Springside的實(shí)現(xiàn)。
其實(shí),實(shí)際上Springside使用的就是經(jīng)典的GenericHibernateDAO+無(wú)Manager的實(shí)現(xiàn)。這么說(shuō)在否定前面所說(shuō),不過(guò)其實(shí)這都是文字游戲:D
首先,對(duì)于Hibernate為主的實(shí)現(xiàn)下,DAO使用Generic是很方便的。Spring的hibernate template受累于向JDK1.4兼容,所以沒(méi)有用generic,但是實(shí)際上DAO是generic的經(jīng)典應(yīng)用。在Hibernate網(wǎng)站上有過(guò)討論。現(xiàn)在Springside使用的GenericHibernateDAO已經(jīng)進(jìn)化的非常先進(jìn)了。
Springside實(shí)際上有Manager,我說(shuō)沒(méi)有其實(shí)是指它的Manager繼承自DAO。看似亂倫,但實(shí)際上非常合理。前面說(shuō)了Manager與DAO的很大區(qū)別在于事物范疇,使用繼承后,兩者之間就可以分離,可以通過(guò)Spring的AOP將事物屬性配置在Manager上,也就解決了問(wèn)題。這應(yīng)該說(shuō)也是template模式的標(biāo)準(zhǔn)應(yīng)用。本來(lái)Manager就有很多方法可以通過(guò)模板實(shí)現(xiàn),而DAO和Generic就很好地解決了他們之間的模板關(guān)系。
我們先看看具體的設(shè)計(jì):
以CustomerManager為例,我們看看類簽名:
CustomerManager extends BaseHibernateDao<Customer>
BaseHibernateDao<T> extends AbstractHibernateDao<T>
AbstractHibernateDao<T> extends HibernateDaoSupport
三層結(jié)構(gòu):
第一層AbstractHibernateDao繼承自大家都熟悉的Spring的HibernateDaoSupport,這一層的主要作用是擴(kuò)展Generic,這樣一方面減少了強(qiáng)行類型轉(zhuǎn)換的啰嗦,一方面使DoaminClass的信息通過(guò)Generic繼承透明聲明。這一層還有一個(gè)作用,就是說(shuō)不管你是否使用Generic,你的應(yīng)用程序最好也在這里增加一層繼承,作用是在需要的時(shí)候你可以在這里擴(kuò)展DAO模版:D
第二層是BaseHibernateDao。這個(gè)其實(shí)是springside很自豪的一個(gè)地方,可以理解,因?yàn)檫@里真的花了很多的代碼,而且相當(dāng)精妙。不賣官子,其實(shí)這里主要給DAO擴(kuò)展了分頁(yè)支持,這顯然是異常重要的,大家google一下就知道分頁(yè)在Web應(yīng)用中的重要性了,基本上你看一個(gè)Java Web Framework都會(huì)看到它對(duì)自己分頁(yè)特性的支持方式介紹,或者說(shuō)分頁(yè)的實(shí)現(xiàn)風(fēng)格已經(jīng)是Java Web Framework實(shí)現(xiàn)優(yōu)劣的一個(gè)標(biāo)準(zhǔn)了。應(yīng)該說(shuō),springsdie的分頁(yè)實(shí)現(xiàn)來(lái)自javaeye上的一個(gè)經(jīng)典的討論,robbin等牛在里面仔細(xì)討論了用DetachedCriteria實(shí)現(xiàn)分頁(yè)查詢,后面引出bug,然后解決,希望沒(méi)看過(guò)的朋友都看看。(應(yīng)用Hibernate3的DetachedCriteria實(shí)現(xiàn)分頁(yè)查詢|http://forum.javaeye.com/viewtopic.php?t=14657&postdays=0&postorder=asc&start=0)
springside的實(shí)現(xiàn)是集大成者,考慮到了Criteria(不僅是DetachedCriteria)、HQL、collection.size()幾種不同實(shí)現(xiàn),也考慮到了使用Criteria的時(shí)候Order造成的問(wèn)題(這個(gè)在我的Blog中給DetachedCriteria擦屁股那個(gè)里面討論過(guò))。
第三層就是具體的Manager,它是用Generic繼承傳遞了DoaminModel的類信息。由于大部分CRUD已經(jīng)在DAO里面實(shí)現(xiàn)了,所以Manager只需要實(shí)現(xiàn)一些需要特殊實(shí)現(xiàn)的method的就可以了,簡(jiǎn)單的應(yīng)用中Manager里面經(jīng)常是空空如也。
其中,BaseHibernateDao的實(shí)現(xiàn)相對(duì)復(fù)雜,主要因?yàn)槔锩姘b了分頁(yè)實(shí)現(xiàn)。大家可以具體看看CriteriaPage和HqlPage兩個(gè)類,這是精妙所在。但是在這一層還有個(gè)CriteriaSetup是個(gè)比較奇怪的東西,一開(kāi)始沒(méi)太看明白是做什么用的。后來(lái)問(wèn)了百衣,他說(shuō)這是為了解決search問(wèn)題提供的,從jsp傳遞過(guò)來(lái)的東西在Controller層可以通過(guò)util(這里springside很CoC,它把search_開(kāi)頭的東西自動(dòng)作為“=”的查詢條件傳給Manager,但目前的缺陷在于只能默認(rèn)處理“=”,其它方式需要擴(kuò)展)處理查詢條件傳給Manager,但是這個(gè)東西設(shè)計(jì)得有點(diǎn)怪,白衣也對(duì)它不滿意,說(shuō)在Springside 2.0里面要重構(gòu)掉,但還沒(méi)有什么好的想法,大家又建議可以提給他。
我認(rèn)為傳遞查詢信息大概需要這樣的設(shè)計(jì):
1、在Controller里面不暴露hibernate API,但是能夠順利將參數(shù)傳遞到Manager。
2、Manager直接傳遞,或者將這些參數(shù)轉(zhuǎn)換為Hibernate API后再傳遞,因?yàn)檫@正是manager需要負(fù)責(zé)的商業(yè)邏輯之一。
3、DAO里面最好不要做那么多轉(zhuǎn)換,畢竟它是持久層。
當(dāng)然,目前符合這個(gè)要求,只是限定于Map是二元容器,不能存3元的查詢條件(key、value、type)。所以可能下一步會(huì)補(bǔ)足。
分析到這里,springside的DAO的結(jié)構(gòu)大概就是這樣的。
感覺(jué)這和我們Team上個(gè)項(xiàng)目的結(jié)構(gòu)很象(不好意思,沒(méi)說(shuō)有springside那么好),有一點(diǎn)區(qū)別。
由于Manager繼承自DAO,我們讓DAO多了很多方法,主要就是想提供方便。尤其是





這些東西經(jīng)常用到,如果使用了會(huì)減少了很多時(shí)候遇到的Manager里面注入其他Domain的DAO,卻只是為了load或者listAll的問(wèn)題(同時(shí)用generic):D
今天有點(diǎn)別的事,先說(shuō)到這里,好好想想,看有什么問(wèn)題過(guò)兩天在說(shuō)說(shuō)。這Blog太流水賬,太空洞,大家見(jiàn)諒。