Java Bean 映射工具 Dozer (转)



 

分析多层架构的JEE系统,经常存在JavaBean直接的拷贝。比如在DAO层,我们通过POJO取得业务层需要的数据,将这些数据传递给Service层的VO。POJO与VO就存在典型的值拷贝。还有就是Webservice,客户端调用Webservice,也存在将大量返回值映射到相应的JavaBean里。呵呵 我们项目就是这个需求。
    典型的解决方案就是手动拷贝,弊端很明显,代码中充斥大量Set Get方法,真正的业务没埋藏与值的拷贝之中。另一种方案就是使用BeanUtil,但BeanUtil不够很好的灵活性,又时候还不得不手动拷贝。
     对于这种重复没有实际意义的拷贝难道没有终结解决方案吗?! Dozer 一把JavaBean利器。(http://dozer.sourceforge.net/)

    什么是Dozer?
    看看官方的定义:

 Dozer is a Java Bean to Java Bean mapper that recursively copies data from one object to 
another. Typically, these Java Beans will be of different complex types.

Dozer supports simple property mapping, complextype mapping, bi
-directional mapping, implicitexplicit mapping, as well as recursive
mapping.This includes mapping collection attributes that also need mapping at the element level.

 注意:Dozer支持简单类型 复杂类型的双向递归映射。
    
    如何使用呢? 类似BeanUtil 很简单,如果两个javaBean之间,属性名相同,类型为基本类型,那么下面代码就OK了,基本没有学习曲线。
   

Mapper mapper = new DozerBeanMapper();

DestinationObject destObject = mapper.map(sourceObject, DestinationObject.class);
//或者
DestinationObject destObject = new DestinationObject();
mapper.map(sourceObject, destObject);

上次大概介绍了为什么要使用Dozer,以及对Dozer一个简单介绍。 今天我们来讨论如何使用Dozer映射复杂类型:
            1. 数据类型不一致。
            2. 级联映射。
            3. 自定义映射。
    在讨论之前,我们来说说一个朋友在上篇留言中提到的一个问题。估计大家应该都很关心。这个问题就是性能问题。Dozer其实底层使用了现成的BeanUtil,通过反射来映射,况且Dozer应用了Cache技术,应该比自个通过BeanUtils映射性能要好点。所以一般的应用应该不存在性能问题。

    Dozer对于基本类型之间转换是不用配置的,比如Sting <------>Integer ,只要属性名称相同就Ok了。
    而常用的Date与String映射配置如下:

<mapping date-format="MM-dd-yyyy">
<class-a>net.blogjava.vincent.pojo.CustomerPo</class-a>
<class-b>net.blogjava.vincent.vo.CustomerVo</class-b>
<field>
<a>birthday</a>
<b>dateOfBirth</b>
</field>
</mapping>

   指明 CustomerPo里面的birthday对应CustomerVo里面的dateOfBirth.并且是Date与String之间双向映射。
    对于属性名称不一致,也仅仅需要一个配置文件,如下:

    <mapping>
       <class-a>net.blogjava.vincent.pojo.CustomerPo</class-a>
       <class-b>net.blogjava.vincent.vo.CustomerVo</class-b>
        <field>
        <a>type</a>
      <b>transferType</b>
    </field>
  </mapping>

 指明 CustomerPo里面的type 对应CustomerVo里面的transferType.
     而对以级联,比如CustomerPo里面的一个属性映射为CustomerVo里么一个对象的属性,下面的配置就可以了

<mapping>
       <class-a>net.blogjava.vincent.pojo.CustomerPo</class-a>
       <class-b>net.blogjava.vincent.vo.CustomerVo</class-b>
        <field>
        <a>type</a>
      <b>transferType.type</b>
    </field>
     </mapping>

上面其实就是Dozer基本用法,也涵盖了大多数应用场景,可见基本不需要写代码,仅仅一个配置文件搞定,简单吧。

      而对以更个性化的映射,就需要写代码了, 比如在CustomerPo中的into类型的transferId ,映射CustomerVo  String 类型transferType, 如果transferId =1 对应transferType=“immediateTranfer” 如果transferId =2 对应transferType=“scheduleTransfer” 反之亦然。就要写一个Customer的Map了, 如下:

import org.dozer.CustomConverter;

public class CustomerMap implements CustomConverter {

    public Object convert(Object destinationFieldValue,
            Object sourceFieldValue, Class<?> destinationClass,
            Class<?> sourceClass) {
        Object returnVale = null;
        if(sourceFieldValue!=null){
            if(sourceFieldValue instanceof Integer ){
                if((Integer)sourceFieldValue == 1){
                    returnVale ="immediateTranfer";
                }
                if((Integer)sourceFieldValue == 2){
                    returnVale ="scheduleTransfer";
                }
                
            }
            if(sourceFieldValue instanceof String ){
                if("immediateTranfer".equals(destinationFieldValue)){
                    returnVale =1;
                }
                if("scheduleTransfer".equals(destinationFieldValue)){
                    returnVale =2;
                }
                
            }

        }
        return returnVale;
    }

}
然后在配置文件配置就Ok了 如下:
  <mapping>
           <class-a>net.blogjava.vincent.pojo.CustomerPo</class-a>
          <class-b>net.blogjava.vincent.vo.CustomerVo</class-b>
        <field custom-converter="net.blogjava.vincent.mapUtil.CustomerMap">
        <a>type</a>
       <b>transferType</b>
       </field>
     </mapping>

下面就是一个完整的配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://dozer.sourceforge.net E:\dozer\dozer-5.0-src\dozer-5.0\src\site\resources\schema\beanmapping.xsd"
    xmlns="http://dozer.sourceforge.net">
    <mapping  date-format="yyyy-MM-dd">
        <class-a>net.blogjava.vincent.pojo.UserInfo</class-a>
        <class-b>net.blogjava.vincent.vo.UserInfoVo</class-b>
        <field>
            <a>colleage.name</a>
            <b>schoolName</b>
        </field>
    </mapping>
        <mapping>
        <class-a>net.blogjava.vincent.pojo.CustomerPo</class-a>
        <class-b>net.blogjava.vincent.vo.CustomerVo</class-b>
         <field custom-converter="net.blogjava.vincent.mapUtil.CustomerMap">
            <a>type</a>
            <b>transferType</b>
        </field>
    </mapping>

</mappings>




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值