JAVA進階:VO(DTO)與PO(DAO)之間的轉換

snoopy7713發表於2011-12-06

 

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.

 

 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屬性的時候達到自己的要求,如:

 

/** //*
 * 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中則可能是此物件的全部屬性。其中的一些轉換則需要依據前臺需要針對性地處理啦!

Reference:  Apache DOC and <>   

 

 

 

相關文章