coding……
但行好事 莫问前程

Bean转换工具DozerBeanMapper

在开发中经常遇到这样一个问题,从DAO层拿回DO实体对象,比如我们从数据库中查出的User实体类包含以下域:

@Getter
@Setter
@ToString
public class UserDO {
    private Integer id;
    private String name;
    private Integer age;
    private String gender;
    private String address;
    private String password;
    private String nickName;
    private Date birthday;
    private Integer isDeleted;
}

但是我们服务需要返回的实体类VO,包含以下域:

@Getter
@Setter
@ToString
public class UserVO {
    private Integer id;
    private String name;
    private Integer age;
    private String gender;
    private String address;
    private String nickName;
    private Date birthday;
    private Integer clickCount;
}

很明显,VO中包含了DO中的大多数域数据,但也没有完全重合。开发中我们需要把DO实体类转成VO实体类,一般的方法可以这样处理:

public class TransformDemo {
    private UserDO userDO = new UserDO();

    @Before
    public void init(){
        userDO.setId(1);
        userDO.setAge(18);
        userDO.setName("zhuoli");
        userDO.setAddress("shanghai");
        userDO.setBirthday(Date.from(LocalDate.of(2000, 1, 1).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()));
        userDO.setGender("male");
        userDO.setNickName("卓立");
        userDO.setPassword("123456");
        userDO.setIsDeleted(0);
    }
    @Test
    public void transformInCommonWay(){
        UserVO userVO = new UserVO();
        userVO.setId(userDO.getId());
        userVO.setAge(userDO.getAge());
        userVO.setName(userDO.getName());
        userVO.setAddress(userDO.getAddress());
        userVO.setBirthday(userDO.getBirthday());
        userVO.setGender(userDO.getGender());
        userVO.setNickName(userDO.getNickName());
        userVO.setClickCount(99);

        System.out.println(userVO);
    }
}

先new一个VO对象,然后调用set方法一一将值塞进去,很不方便。另外分层的结构有个很鲜明的特点,DO和VO有很多重复的字段,我们是不是可以利用这个特点快捷的讲DO转成VO?下面就介绍一下可以完成这个工作的一个工具Dozer 。

1. Dozer简介

Dozer是Java Bean到Java Bean映射器,它以递归方式将数据从一个对象复制到另一个对象。支持简单属性映射,复杂类型映射,双向映射,隐式显式映射以及递归映射。另外,Dozer不仅支持属性名称之间的映射,还支持在类型之间自动转换。大多数转换方案都是开箱即用的,如果无法完成映射(比如使用属性名映射的时候,名称不同),还允许通过xml配置文件的形势配置映射规则。Dozer官方给出如下的使用场景:

Dozer通常用于整个系统的入口和出口,可以保证数据库中的内部域对象不会流入外部表示层或外部使用者,还可以帮助将域对象映射到外部API调用,反之亦然。

2. 自定义BeanMapper工具类

了解了Dozer常规使用后,下面我使用Dozer实现一个工具类,基于属性名称进行对象映射。至于类型映射和自定义映射配置这里就不讲解了,可以去看一下官方文档,很好理解。这里仅展现基于Dozer的对象转换工具类。

2.1 BeanMapper

public class BeanMapper {

    private static DozerBeanMapper dozer = new DozerBeanMapper();

    /**
     * 普通对象转换 比如: ADO -> AVO
     * @param: [source 源对象, destinationClass 目标对象class]
     * @return: T
     * @author: zhuoli
     * @date: 2018/9/30 18:13
     */
    public static <T> T map(Object source, Class<T> destinationClass) {
        if (source == null) {
            return null;
        }
        return dozer.map(source, destinationClass);
    }

    /**
     * List转换 比如: List<ADO> -> List<AVO>
     * @param: [sourceList 源对象List, destinationClass 目标对象class]
     * @return: java.util.List<T>
     * @author: zhuoli
     * @date: 2018/9/30 18:14
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static <T> List<T> mapList(Collection sourceList, Class<T> destinationClass) {
        List<T> destinationList = new ArrayList();
        if (sourceList == null) {
            return destinationList;
        }
        for (Object sourceObject : sourceList) {
            if (sourceObject != null) {
                T destinationObject = dozer.map(sourceObject, destinationClass);
                destinationList.add(destinationObject);
            }
        }
        return destinationList;
    }
}

2.2 BeanMapper使用

@Test
public void transformInDozerWay(){
    UserVO userVO = BeanMapper.map(userDO, UserVO.class);
    userVO.setClickCount(99);
    System.out.println(userVO);
}
UserVO(id=1, name=zhuoli, age=18, gender=male, address=shanghai, nickName=卓立, birthday=Sat Jan 01 00:00:00 CST 2000, clickCount=99)

使用工具类如上就可以方便地完成对象地转换,只要代码中使用统一的编码规范(在进行属性命名时,各层使用相同的名称),使用上述工具类进行对象转换是比较方便的。

示例代码:码云 – 卓立 – 对象转换工具

赞(0) 打赏
Zhuoli's Blog » Bean转换工具DozerBeanMapper
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址