posts - 120,  comments - 19,  trackbacks - 0
          ??關(guān)于VO、PO的理解


          O/R Mapping 是 Object Relational Mapping(對象關(guān)系映射)的縮寫。通俗點講,就是將對象與關(guān)系數(shù)據(jù)庫綁定,用對象來表示關(guān)系數(shù)據(jù)。在O/R Mapping的世界里,有兩個基本的也是重要的東東需要了解,即VO,PO。
            VO,值對象(Value Object),PO,持久對象(Persisent Object),它們是由一組屬性和屬性的get和set方法組成。從結(jié)構(gòu)上看,它們并沒有什么不同的地方。但從其意義和本質(zhì)上來看是完全不同的。

          1.VO是用new關(guān)鍵字創(chuàng)建,由GC回收的。
            PO則是向數(shù)據(jù)庫中添加新數(shù)據(jù)時創(chuàng)建,刪除數(shù)據(jù)庫中數(shù)據(jù)時削除的。并且它只能存活在一個數(shù)據(jù)庫連接中,斷開連接即被銷毀。

          2.VO是值對象,精確點講它是業(yè)務(wù)對象,是存活在業(yè)務(wù)層的,是業(yè)務(wù)邏輯使用的,它存活的目的就是為數(shù)據(jù)提供一個生存的地方。
            PO則是有狀態(tài)的,每個屬性代表其當(dāng)前的狀態(tài)。它是物理數(shù)據(jù)的對象表示。使用它,可以使我們的程序與物理數(shù)據(jù)解耦,并且可以簡化對象數(shù)據(jù)與物理數(shù)據(jù)之間的轉(zhuǎn)換。

          3.VO的屬性是根據(jù)當(dāng)前業(yè)務(wù)的不同而不同的,也就是說,它的每一個屬性都一一對應(yīng)當(dāng)前業(yè)務(wù)邏輯所需要的數(shù)據(jù)的名稱。
            PO的屬性是跟數(shù)據(jù)庫表的字段一一對應(yīng)的。

          PO對象需要實現(xiàn)序列化接口。

          (轉(zhuǎn)載:http://www.matrix.org.cn/resource/article/43/43869.html
          --------------------------------------------
          在 struts+ hibernate 這種結(jié)構(gòu)中,是不應(yīng)該把Hibernate產(chǎn)生的PO直接傳遞給JSP的,不管他是

          Iterator,還是List,這是一個設(shè)計錯誤。

          我來談?wù)勗贘2EE架構(gòu)中各層的數(shù)據(jù)表示方法:

          Web層的數(shù)據(jù)表示是FormBean,數(shù)據(jù)來源于HTML Form POST
          業(yè)務(wù)層的數(shù)據(jù)表示是VO
          持久層的數(shù)據(jù)表示是PO,其數(shù)據(jù)來源于數(shù)據(jù)庫,持久層的數(shù)據(jù)表示例如CMP

          在一個規(guī)范的J2EE架構(gòu)中,不同層的數(shù)據(jù)表示應(yīng)該被限制在層內(nèi),而不應(yīng)該擴(kuò)散到其它層,這樣可以降

          低層間的耦合性,提高J2EE架構(gòu)整體的可維護(hù)性和可擴(kuò)展性。比如說Web層的邏輯進(jìn)行了修改,那么只需

          要修改FormBean的結(jié)構(gòu),而不需要觸動業(yè)務(wù)層和持久層的代碼修改。同樣滴,當(dāng)數(shù)據(jù)庫表進(jìn)行了小的調(diào)

          整,那么也只需要修改持久層數(shù)據(jù)表示,而不需要觸動業(yè)務(wù)層代碼和Web層代碼。

          不過由于Hibernate的強(qiáng)大功能,例如動態(tài)生成PO,PO的狀態(tài)管理可以脫離Session,使得在應(yīng)用了

          Hibernate的J2EE框架中,PO完全可以充當(dāng)VO,因此我們下面把PO和VO合并,統(tǒng)稱為PO。

          先來談?wù)凙ctionFormBean和持久層的PO之間的重大區(qū)別。

          在簡單的應(yīng)用中,ActionFormBean和PO幾乎是沒有區(qū)別,所以很多人干脆就是用ActionFormBean來充當(dāng)

          PO,于是ActionFormBean從JSP頁面到Servlet控制層再到業(yè)務(wù)層,然后穿過持久層,最后一直映射到數(shù)

          據(jù)庫表。真是一竿子捅到了底!

          但是在復(fù)雜的應(yīng)用中,ActionFormBean和PO是分離的,他們也不可能一樣。ActionFormBean是和網(wǎng)頁里

          面的Form表單一一對應(yīng)的,F(xiàn)orm里面有什么元素,Bean里面就有什么屬性。而PO和數(shù)據(jù)庫表對應(yīng),因此

          如果數(shù)據(jù)庫表不修改,那么PO也不會修改,如果頁面的流程和數(shù)據(jù)庫表字段對應(yīng)關(guān)系不一致,那么你又

          如何能夠使用ActionFormBean來取代PO呢?

          比如說吧,用戶注冊頁面要求注冊用戶的基本信息,因此HTML Form里面包含了基本信息屬性,于是你需

          要一個ActionFormBean來一一對應(yīng)(注意:是一一對應(yīng)),每個Bean屬性對應(yīng)一個文本框或者選擇框什么

          的。

          而用戶這個持久對象呢?他的屬性和ActionFormBean有什么明顯不同呢?他會有一些ActionFormBean所

          沒有的集合屬性,比如說用戶的權(quán)限屬性,用戶的組屬性,用戶的帖子等等。另外還有可能的是在

          ActionFormBean里面有3個屬性,分別是用戶的First Name, Middle Name, Last Name,而在我的User這

          個持久對象中就是一個 Name 對象屬性。

          假設(shè)我的注冊頁面原來只要你提供First Name,那么ActionFormBean就這一個屬性,后來我要你提供全

          名,你要改ActionFormBean,加兩個屬性。但是這個時候PO是不應(yīng)該修改滴,因為數(shù)據(jù)庫沒有改。

          那么在一個完整的J2EE系統(tǒng)中應(yīng)該如何進(jìn)行合理的設(shè)計呢?

          JSP(View) ---> ActionFormBean(Module) ---> Action(Control)

          ActionFormBean是Web層的數(shù)據(jù)表示,它和HTML頁面Form對應(yīng),只要Web頁面的操作流程發(fā)生改變,它就

          要相應(yīng)的進(jìn)行修改,它不應(yīng)該也不能被傳遞到業(yè)務(wù)層和持久層,否則一旦頁面修改,會一直牽連到業(yè)務(wù)

          層和持久層的大面積的代碼進(jìn)行修改,對于軟件的可維護(hù)性和可擴(kuò)展性而言,是一個災(zāi)難,Actiont就是

          他的邊界,到此為止!

          Action(Web Control) ---> Business Bean ---> DAO ---> ORM --->DB

          而PO則是業(yè)務(wù)層和持久層的數(shù)據(jù)表示,它在業(yè)務(wù)層和持久層之間進(jìn)行流動,他不應(yīng)該也不能被傳遞到Web

          層的View中去,而ActionServlet就是他的邊界,到此為止!

          然后來看一看整個架構(gòu)的流程:

          當(dāng)用戶通過瀏覽器訪問網(wǎng)頁,提交了一個頁面。于是Action拿到了這個FormBean,他會把FormBean屬性

          讀出來,然后構(gòu)造一個PO對象,再調(diào)用業(yè)務(wù)層的Bean類,完成了注冊操作,重定向到成功頁面。而業(yè)務(wù)

          層Bean收到這個PO對象之后,調(diào)用DAO接口方法,進(jìn)行持久對象的持久化操作。

          當(dāng)用戶查詢某個會員的信息的時候,他用全名進(jìn)行查詢,于是Action得到一個UserNameFormBean包括了3

          個屬性,分別是first name, middle name, last name,然后Action把UserNameFormBean的3個屬性讀出

          來,構(gòu)造Name對象,再調(diào)用業(yè)務(wù)Bean,把Name對象傳遞給業(yè)務(wù)Bean,進(jìn)行查詢。

          業(yè)務(wù)Bean取得Name(注意: Name對象只是User的一個屬性)對象之后調(diào)用DAO接口,返回一個User的PO對象

          ,注意這個User不同于在Web層使用的UserFormBean,他有很多集合屬性滴。然后業(yè)務(wù)Bean把User對象返

          回給Action。

          Action拿到User之后,把User的基本屬性取出(集合屬性如果不需要就免了),構(gòu)造UserFormBean,然后

          把UserFormBean request.setAttribute(...),然后重定向到查詢結(jié)果頁面。

          查詢頁面拿到request對象里面的ActionFormBean,自動調(diào)用tag顯示之。

          總結(jié):

          FormBean是Web層的數(shù)據(jù)表示,他不能被傳遞到業(yè)務(wù)層;PO是持久層的數(shù)據(jù)表示,在特定情況下,例如

          Hibernate中,他可以取代VO出現(xiàn)在業(yè)務(wù)層,但是不管PO還是VO都必須限制在業(yè)務(wù)層內(nèi)使用,最多到達(dá)

          Web層的Control,絕不能被擴(kuò)散到View去。

          FormBean和PO之間的數(shù)據(jù)轉(zhuǎn)化是在Action中進(jìn)行滴。

          BTW:

          JDO1.x還不能像Hibernate功能這樣強(qiáng)大,PO不能脫離持久層,所以必須在業(yè)務(wù)層使用VO,因此必須在業(yè)

          務(wù)層進(jìn)行大量的VO和PO的轉(zhuǎn)化操作,相對于Hibernate來說,編程比較煩瑣。

          當(dāng)然咯,理論是一回事,實際操作也不一定非要這樣干,你可以自行取舍,在實際項目中靈活一點,增

          加一點bad smell,提高開發(fā)效率。只不過在大型項目中最好還是嚴(yán)絲合縫,不然的話,改版的時候會痛

          苦的很滴。
          (轉(zhuǎn)載:http://forum.hibernate.org.cn/viewtopic.php?t=627



          posted on 2006-08-16 13:51 阿成 閱讀(536) 評論(0)  編輯  收藏 所屬分類: J2EE
          主站蜘蛛池模板: 都兰县| 阿瓦提县| 襄汾县| 宜良县| 华蓥市| 广宁县| 怀来县| 磐安县| 加查县| 宁城县| 汾阳市| 鄂州市| 兴海县| 报价| 沁水县| 木兰县| 香河县| 深泽县| 岫岩| 弥勒县| 西平县| 中阳县| 达孜县| 岳阳县| 台安县| 伊宁市| 金乡县| 连江县| 琼结县| 泰来县| 五莲县| 博客| 清流县| 东兴市| 石家庄市| 青阳县| 新干县| 阳山县| 卓尼县| 思南县| 塔河县|