PO即 Persistence Object
VO即 Value Object
VO和PO的主要区别在于:
VO是独立的Java Object。
PO是由Hibernate纳入其实体容器(Entity Map)的对象,它代表了与数据库中某条记录对应的Hibernate实体,PO的变化在事务提交时 将 反应到实际数据库中。
实际上,这个VO被用作Data Transfer Object,即所谓的DTO。想必,VO就是Data Access Object ---DAO了啦。为什么要有这二者之分呢?如在传统的MVC架构中,位于Model层的PO,是否允许被传递到其他层面。由于PO的更新最终将被映射到实际数据库中,如果PO在其他层面(如View层)发生了变动,那么可能会对Model层造成意想不到的破坏。
主要想说的还是如何进行二者之间的转换:
属性复制可以通过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中则可能是此对象的全部属性。其中的一些转换则需要依据前台需 要针对性地处理啦!
在copy的过程中,若实体中存在一对多,多对多等关系,则DTO中也应该存在此关系,此时不能直接将内部的DTO or List(一对多)里面的数据一次性全部拷过去,这时应该对每个DTO进行copy,当然,若在前台你无需用到相关的DTO则可以跳过。而对于一对多(LIST),而应将实体里面的每个一对多转换成对应的DTO,再依次放到LSIT里面,再将此LIST赋值给(父)DTO,这里面的关系如同(一个简单的)递归关系。---