JAVA进阶:VO(DTO)与PO(DAO)之间的转换

PO---Persistence Object顾名思义就是持久化对象
VO---Value Object可以认为是用作暂时保存值的对象,与数据库并不相关
实际上,VO被用作Data Transfer Object,就是所谓的DTO。想必,VO就是Data Access Object---DAO啦。为什么要有这两者之分呢?这要从MVC框架理论中进行说明,在传统的MVC架构中,强调三层结构,然后位于Model层的PO,与数据库是紧密相连的,如果PO传递到VIEW层,在VIEW层中被修改了,那会造成意想不到的结果。
属性复制可以通过Apache Jakarta Commons Beanutils(http://jakarta.apache.org/commons/beanutils/)组件提供的属性批量复制功能,避免繁复的get/set操作。down下来之后,里面的API DOC一应俱全。

 对于一些无需处理其它处理(如过滤)直接用BeanUtilsBean.copyProperties方法,其参考如下:

public static void copyProperties(java.lang.Object dest,

java.lang.Object orig)

throws java.lang.IllegalAccessException,

java.lang.reflect.InvocationTargetExceptioCopy property values from the origin bean to the destination bean for all cases where the property names are the same.



  范例1:

TUser user = new TUser();

TUser anotherUser = new TUser();

user.setName( " Emma " );

user.setUserType( 1 );

try {

BeanUtils.copyProperties(anotherUser,user);

System.out.println( " UserName => "

+ anotherUser.getName()

);

System.out.println( " UserType => "

+ anotherUser.getUserType()

);

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}  




 也可以利用其中的一些方法在copy属性的时候达到自己的要求,如:

 范例2

/** */ /** //*

* Created on 2006-4-26

*/

package com.util;


import java.beans.PropertyDescriptor;

import java.util.Collection;


import org.apache.commons.beanutils.PropertyUtils;


/** */ /** */ /** */ /**

* CopyUtil

* @author Jkallen

*/

public class CopyUtil {



/** */ /** */ /** */ /**

* Copy properties of orig to dest

* Exception the Entity and Collection Type

* @param dest

* @param orig

* @return the dest bean

*/

public static Object copyProperties(Object dest, Object orig) {

if (dest == null || orig == null ) {

return dest;

}



PropertyDescriptor[] destDesc = PropertyUtils.getPropertyDescriptors(dest);

try {

for ( int i = 0 ; i < destDesc.length; i ++ ) {

Class destType = destDesc[i].getPropertyType();

Class origType = PropertyUtils.getPropertyType(orig, destDesc[i].getName());

if (destType != null && destType.equals(origType)

&& ! destType.equals(Class. class )) {

if ( ! Collection. class .isAssignableFrom(origType)) {

try {

Object value = PropertyUtils.getProperty(orig, destDesc[i].getName());

PropertyUtils.setProperty(dest, destDesc[i].getName(), value);

} catch (Exception ex) {

}

}

}

}



return dest;

} catch (Exception ex) {

throw new CopyException(ex);

// return dest;

}

}



/** */ /** */ /** */ /**

* Copy properties of orig to dest

* Exception the Entity and Collection Type

* @param dest

* @param orig

* @param ignores

* @return the dest bean

*/

public static Object copyProperties(Object dest, Object orig, String[] ignores) {

if (dest == null || orig == null ) {

return dest;

}



PropertyDescriptor[] destDesc = PropertyUtils.getPropertyDescriptors(dest);

try {

for ( int i = 0 ; i < destDesc.length; i ++ ) {

if (contains(ignores, destDesc[i].getName())) {

continue ;

}



Class destType = destDesc[i].getPropertyType();

Class origType = PropertyUtils.getPropertyType(orig, destDesc[i].getName());

if (destType != null && destType.equals(origType)

&& ! destType.equals(Class. class )) {

if ( ! Collection. class .isAssignableFrom(origType)) {

Object value = PropertyUtils.getProperty(orig, destDesc[i].getName());

PropertyUtils.setProperty(dest, destDesc[i].getName(), value);

}

}

}



return dest;

} catch (Exception ex) {

throw new CopyException(ex);

}

}



static boolean contains(String[] ignores, String name) {

boolean ignored = false ;

for ( int j = 0 ; ignores != null && j < ignores.length; j ++ ) {

if (ignores[j].equals(name)) {

ignored = true ;

break ;

}

}



return ignored;

}

}





  

  可以看到,在范例1中通过方法copyProperties的时候,二者之间在的属性名必须相同(Copy property values from the origin bean to the destination bean for all cases where the property names are the same)。而在范例2中通过

  Object value = PropertyUtils.getProperty(orig, destDesc[i].getName());

  PropertyUtils.setProperty(dest, destDesc[i].getName(), value);

  也是将源与目的之间copy相同的属性名。而VO是在前台显示,所以难免会用到PO中所不存在的属性值。比如PO中可能是一个对象,而VO中则可能是此对象的全部属性。其中的一些转换则需要依据前台需要针对性地处理啦!
本周的技术研讨会上,部门的同事就PO和VO的使用提出了不同意见,和hibernate中文网站的争论一样,形成了两派意见,一派是PO可以用在商业逻辑层,当作VO使用,一派是不同意这种看法,认为PO用在商业逻辑层不合适,我就是这一派的支持者。
在会上我说了自己的观点和理由:
PO只能用在数据层,VO用在商业逻辑层和表示层。各层操作属于该层自己的数据对象,这样就可以降低各层之间的耦合,便于以后系统的维护和扩展。如果将PO用在各个层中就相当于我们使用全局变量,我们知道在OO设计非常不赞成使用全局变量。
当然我们在实际项目中有时候会在某个商业逻辑或者表示层使用PO,我觉得只有当下列条件满足的时候,这样做是可以允许的:
那就是在这个商业逻辑的过程中PO的状态是不发生变化的,比如显示一条商品详细信息的商业逻辑。
总结:
不管是对类的设计还是系统的设计,原则都是一致的:类、系统的各个部分功能要独立简单,封装性好,逻辑和数据都要保持独立。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值