<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java海闊天空

    編程是我的生活,但生活不僅僅是編程。

    基于SSH2框架構(gòu)建JavaEE應(yīng)用程序(2)

    四、數(shù)據(jù)傳輸、數(shù)據(jù)模型與Dozer

    數(shù)據(jù)傳輸是程序員實現(xiàn)各種功能時刻需要考慮的問題,從數(shù)據(jù)模型的建立,到數(shù)據(jù)模型的轉(zhuǎn)換,從數(shù)據(jù)的合法性驗證,到數(shù)據(jù)類型的轉(zhuǎn)化,我們要時刻小心,精心設(shè)計與組織。數(shù)據(jù)模型與數(shù)據(jù)傳輸可簡單可復(fù)雜,完全取決于設(shè)計者的經(jīng)驗與意圖,當(dāng)然,項目的規(guī)模也是我們應(yīng)該考慮的因素,一個小型項目實在沒必要將問題復(fù)雜化。


    我們首先考慮數(shù)據(jù)從視圖(View)傳輸?shù)綌?shù)據(jù)庫(DB)的數(shù)據(jù)模型變化過程。用戶從界面輸入數(shù)據(jù),此時,數(shù)據(jù)毫無結(jié)構(gòu)可言,是零散的、無組織的,數(shù)據(jù)提交到控制器后,一方面考慮到OOP的嚴(yán)謹(jǐn)性,另一方面考慮到數(shù)據(jù)的封裝,會將零散的無組織的數(shù)據(jù)封裝成Value Object(簡稱VO)對象,VO就是JavaBean,并傳送到業(yè)務(wù)類中,在數(shù)據(jù)模型比較復(fù)雜的情況下,業(yè)務(wù)類的方法參數(shù)和返回值都應(yīng)該是VOVO的集合,VO轉(zhuǎn)換成POPersistence Object)后傳送到DAODAO調(diào)用Hibernate API持久化數(shù)據(jù)。簡單來說,業(yè)務(wù)類對外暴露的數(shù)據(jù)模型是VODAO對外暴露的數(shù)據(jù)模型是PO


    數(shù)據(jù)從數(shù)據(jù)庫傳遞到視圖層的數(shù)據(jù)模型變化恰恰相反,Hibernate將數(shù)據(jù)庫中的記錄轉(zhuǎn)換成POPO傳遞給業(yè)務(wù)類后轉(zhuǎn)換成VOVO被傳送到視圖層進(jìn)行顯示處理。


    以上轉(zhuǎn)換過程如下圖:



     

    為什么同時需要POVO?前面說過,這不是必須的,如果項目比較小,直接使用PO就行了。但PO有如下缺點(diǎn):


    PO反應(yīng)了數(shù)據(jù)庫的物理模型,向外暴露PO存在一定的風(fēng)險;

    PO過于僵化,無法適應(yīng)變化莫測的業(yè)務(wù)需求;

    PO在持久化狀態(tài)下與數(shù)據(jù)庫同步,可能導(dǎo)致數(shù)據(jù)意外修改;

    PO將導(dǎo)致程序缺乏健壯性。


    VO沒有PO的缺點(diǎn),相對而言,VO更加靈活,能適應(yīng)各種需求的變化,下面是POVO的區(qū)別:


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

    VO是值對象,精確點(diǎn)講它是業(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)換;

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

    PO一般只有一個,但對應(yīng)的VO可能有多個。


    我們舉一個簡單的例子來說明VOPO的區(qū)別:比如要實現(xiàn)用戶注冊與登陸的功能,在物理模型中創(chuàng)建一個用戶表,字段分別為用戶ID(標(biāo)識列)、用戶名、密碼、注冊日期等等,定義PO時應(yīng)該有這四個字段的映射屬性。現(xiàn)在,我們來實現(xiàn)用戶注冊這一功能,為了接收用戶輸入的注冊信息,必須定義VO,注冊用戶需要輸入的信息有:用戶名、密碼1、密碼2,這正好是VO的屬性。而實現(xiàn)用戶登陸功能時,用戶需要輸入的信息只有用戶名和密碼,所以,該VO的屬性只有兩個:用戶名、密碼。可以看出,PO側(cè)重于物理模型,而VO則更關(guān)注用戶的實際需求。如下圖所示:



     


    因為數(shù)據(jù)傳輸是雙向的,所以VOPO之間存在相互轉(zhuǎn)換的問題,這會給編程帶來麻煩,我們總是要通過getter方法取出數(shù)據(jù),再通過setter方法給對方屬性賦值,在屬性很多的情況下,讓人深感繁瑣,而Dozer工具能簡化這個問題。


    Dozerhttp://dozer.sourceforge.net/)是一個JavaBean映射工具,能實現(xiàn)對象屬性值之間的相互賦值,Dozer支持簡單類型映射、復(fù)合類型映射、雙向映射以及遞歸映射,默認(rèn)情況下,Dozer能實現(xiàn)類型相同、名字相同的屬性之間的賦值,如果屬性名不同,則必須在xmldozerBeanMapping.xml)配置文件中指定,如果不必為JavaBean的每個屬性賦值,也可以在xml中指定。Xml的定義可以參考http://dozer.sourceforge.net/dtd/dozerbeanmapping.dtd,典型的結(jié)構(gòu)如下:


    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE mappings PUBLIC "-//DOZER//DTD MAPPINGS//EN"

    "http://dozer.sourceforge.net/dtd/dozerbeanmapping.dtd">

    <mappings>

    <configuration>

    <stop-on-errors>false</stop-on-errors>

    <date-format>MM/dd/yyyy HH:mm</date-format>

    <wildcard>true</wildcard>

    </configuration>

    <mapping>

    <class-a>com.denny_blue.dozerdemo.Book</class-a>

    <class-b>com.denny_blue.dozerdemo.CookBook</class-b>

    <field>

    <a>name</a>

    <b>bookName</b>

    </field>

    <field>

    <a>author</a>

    <b>author</b>

    </field>

    </mapping>

    </mappings>


    <class-a>指定所要復(fù)制的源對象,<class-b>復(fù)制的目標(biāo)對象,<a>源對象的屬性名, <b>目標(biāo)對象的屬性名。wildcard默認(rèn)為true,在此時默認(rèn)對所有屬性進(jìn)行map,如果為false,則只對在xml文件中配置的屬性進(jìn)行map


    其中,BookCookBook類分別定義如下:


    public class Book{

    public Book(){

      

    public void setAuthor(String author) {

    this.author = author; 

    }

    public String getAuthor() {

    return (this.author); 

    }

    public void setName(String name){

    this.name=name;

    public String getName(){

    return this.name;

    }

    }

    public class CookBook {

    private String bookName;

    private String author;

    public CookBook(){}

    public String getBookName() {

    return (this.bookName); 

    }

    public void setBookName(String bookName) {

    this.bookName = bookName; 

    }

    public String getAuthor() {

    return (this.author); 

    }

    public void setAuthor(String author) {

    this.author = author; 

    }

    }


    以下是測試代碼:


    Book book1=new Book();

    book1.setAuthor("dennis");

    book1.setName("dozer demo");

    DozerBeanMapper mapper=new DozerBeanMapper();

    book2=(Book)mapper.map(book1,com.denny_blue.dozerdemo.Book.class);

    CookBook cookBook=new CookBook();

    List myMappingFiles = new ArrayList();

    myMappingFiles.add("dozerBeanMapping.xml");

    mapper.setMappingFiles(myMappingFiles);

    cookBook=(CookBook)mapper.map(book1,CookBook.class);

    System.out.println("cookBook's name:"+   cookBook.getBookName()+"     cookBook's author:"+

      cookBook.getAuthor());

    }


    通過mapper.setMappingFiles()設(shè)置映射文件,可以添加多個配置文件,也可以把所有的映射寫在一個配置文件里面。這里介紹的只是最基本的使用方法,為了實現(xiàn)Dozer的模塊化應(yīng)用,我專門寫了一個VoPoConverter類簡化Dozer的調(diào)用。


    package com.aptech.util;

    import java.util.ArrayList;

    import java.util.List;

    import org.dozer.DozerBeanMapper;

    import org.dozer.Mapper;

    /**

     * VOPO相互轉(zhuǎn)換的類

     */

    public class VoPoConverter {

    /**

     * VOPO之間相互轉(zhuǎn)換,將源對象的同名屬性復(fù)制目標(biāo)對象中

     * 前提:源對象和目標(biāo)對象都必須存在

     * @param src 源對象

     * @param desc 目標(biāo)對象

     */

    public static void copyProperties(Object src, Object desc){

    if(src == null) return;

    Mapper mapper = new DozerBeanMapper();

    mapper.map(src, desc);

    }

    /**

     * VOPO之間相互轉(zhuǎn)換,先創(chuàng)建對象,再將源對象的同名屬性復(fù)制目標(biāo)對象中

     * @param <T> 目標(biāo)類型

     * @param src 源對象

     * @param descType 目標(biāo)類型

     * @return

     */

    public static <T> T copyProperties(Object src, Class<T> descType){

    if(src == null) return null;

    Mapper mapper = new DozerBeanMapper();

    return mapper.map(src, descType);

    }

    /**

     * 將源集合轉(zhuǎn)換為目標(biāo)集合,注意:目標(biāo)集合是新建的

     * @param <T>

     * @param srcList 源集合

     * @param descType 目標(biāo)集合中元素的類型

     * @return

     */

    public static <T> List<T> copyList(List srcList, Class<T> descType){

    if(srcList == null) return null;

    List<T> descList = new ArrayList<T>();

    for(Object obj : srcList){

    T t = VoPoConverter.copyProperties(obj, descType);

    descList.add(t);

    }

    return descList;

    }

    }


    類名的意思雖然叫VOPO轉(zhuǎn)換器,實際上可以應(yīng)用在任何場合。如果要配合xml配置文件,該類還需要做一些修改。


    ——作者:李贊紅 (lifenote@21cn.com),轉(zhuǎn)載請保留版權(quán)!

    posted on 2011-02-21 11:43 李贊紅 閱讀(3057) 評論(3)  編輯  收藏

    評論

    # re: 基于SSH2框架構(gòu)建JavaEE應(yīng)用程序(2)[未登錄] 2011-02-21 14:05 littleJava

    基于SSH2框架構(gòu)建JavaEE應(yīng)用程序 1 2 兩部分寫的很精彩。關(guān)于po vo的區(qū)別我以前也有疑問,但是從來沒有像樓主寫的這么細(xì)致,謝謝!后面關(guān)于Dozer的介紹可以單獨(dú)寫一篇文章,寫在這里就有些喧賓奪主了。  回復(fù)  更多評論   

    # re: 基于SSH2框架構(gòu)建JavaEE應(yīng)用程序(2) 2011-02-21 16:04 窩窩影視

    不錯 就是看著有點(diǎn)亂!  回復(fù)  更多評論   

    # re: 基于SSH2框架構(gòu)建JavaEE應(yīng)用程序(2) 2011-02-21 17:31 jackerxff

    好像就是推廣Dozer的,實際完全沒有必要這樣,使PO映射表,VO映射視圖,PO同樣可以new ,PO的映射同樣也可以相當(dāng)?shù)撵`活:查詢使用視圖VO,添加更新使用PO(添加的PO就是new的,更新使用id先get出來,更新后的對象(也是new的)利用反射將值注入get出來的對象中,再update),刪除只需一個id即可,無論P(yáng)O還是VO都可以比較靈活通過@Transient提供的離線字段。。。。就先簡單說點(diǎn)
      回復(fù)  更多評論   


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     

    導(dǎo)航

    <2011年2月>
    303112345
    6789101112
    13141516171819
    20212223242526
    272812345
    6789101112

    統(tǒng)計

    常用鏈接

    留言簿(12)

    隨筆檔案(28)

    相冊

    技術(shù)友情博客

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲妓女综合网99| 国产精品亚洲专区无码WEB| 国产精品成人亚洲| 日韩精品在线免费观看| 国内自产少妇自拍区免费| 亚洲香蕉成人AV网站在线观看| 亚洲电影在线播放| 免费一级做a爰片久久毛片潮| 无码人妻精品中文字幕免费| 免费国产高清视频| 亚洲综合无码一区二区三区| 免费人成大片在线观看播放电影| 37pao成人国产永久免费视频| 亚洲AV成人精品日韩一区18p| 亚洲欧洲高清有无| A国产一区二区免费入口| 四色在线精品免费观看| 亚洲AV日韩AV高潮无码专区| 精品免费AV一区二区三区| 最近免费中文字幕大全免费 | 亚洲av永久中文无码精品| 免费国产在线视频| 亚洲日韩精品无码专区网站| 亚洲jjzzjjzz在线观看| 日本亚洲欧洲免费天堂午夜看片女人员 | 四虎影在线永久免费观看| 亚洲激情校园春色| 免费在线黄色电影| 婷婷亚洲天堂影院| 亚洲日日做天天做日日谢| 久久午夜免费鲁丝片| 中文字幕日韩亚洲| 狠狠入ady亚洲精品| 在线观看无码AV网站永久免费| 亚洲AV无码成人精品区在线观看 | 国产大片51精品免费观看| 亚洲国产精品成人精品小说| 国内永久免费crm系统z在线| 亚洲精品WWW久久久久久 | 日本亚洲欧美色视频在线播放| 免费视频爱爱太爽了|