这篇文章是本人在阅读Dozer官方文档(5.5.1版本,官网已经一年多没更新了)的过程中,整理下来我认为比较基础的应用场景。

本文中提到的例子应该能覆盖JavaBean映射的大部分场景,希望对你有所帮助。

概述

Dozer是什么?

Dozer是一个JavaBean映射工具库。

它支持简单的属性映射,复杂类型映射,双向映射,隐式显式的映射,以及递归映射。

它支持三种映射方式:注解、API、XML。

安装

引入jar包

maven方式

如果你的项目使用maven,添加以下依赖到你的pom.xml即可:

net.sf.dozer

dozer

5.4.0

非maven方式

如果你的项目不使用maven,那就只能发扬不怕苦不怕累的精神了。

使用Dozer需要引入Dozer的jar包以及其依赖的第三方jar包。

Eclipse插件

Dozer有插件可以在Eclipse中使用(不知道是否好用,反正我没用过)

插件地址: http://dozer.sourceforge.net/eclipse-plugin

使用

将Dozer引入到工程中后,我们就可以来小试一番了。

实践出真知,先以一个最简单的例子来展示Dozer映射的处理过程。

准备

我们先准备两个要互相映射的类

NotSameAttributeA.java

public class NotSameAttributeA {

private long id;

private String name;

private Date date;

// 省略getter/setter

}

NotSameAttributeB.java

public class NotSameAttributeB {

private long id;

private String value;

private Date date;

// 省略getter/setter

}

这两个类存在属性名不完全相同的情况:name 和 value。

Dozer的配置

为什么要有映射配置?

如果要映射的两个对象有完全相同的属性名,那么一切都很简单。

只需要直接使用Dozer的API即可:

Mapper mapper = new DozerBeanMapper();

DestinationObject destObject =

mapper.map(sourceObject, DestinationObject.class);

但实际映射时,往往存在属性名不同的情况。

所以,你需要一些配置来告诉Dozer应该转换什么,怎么转换。

注:官网着重建议:在现实应用中,最好不要每次映射对象时都创建一个Mapper实例来工作,这样会产生不必要的开销。如果你不使用IoC容器(如:spring)来管理你的项目,那么,最好将Mapper定义为单例模式。

映射配置文件

在src/test/resources目录下添加dozer/dozer-mapping.xml文件。

标签中允许你定义和,对应着相互映射的类。

标签里定义要映射的特殊属性。需要注意和对应,和对应,聪明的你,猜也猜出来了吧。

xsi:schemaLocation="http://dozer.sourceforge.net

http://dozer.sourceforge.net/schema/beanmapping.xsd">

org.zp.notes.spring.common.dozer.vo.NotSameAttributeA

org.zp.notes.spring.common.dozer.vo.NotSameAttributeB

name

value

与Spring整合

配置 DozerBeanMapperFactoryBean

在src/test/resources目录下添加spring/spring-dozer.xml文件。

Dozer与Spring的整合很便利,你只需要声明一个DozerBeanMapperFactoryBean,

将所有的dozer映射配置文件作为属性注入到mappingFiles,

DozerBeanMapperFactoryBean会加载这些规则。

spring-dozer.xml文件范例

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"

default-autowire="byName" default-lazy-init="false">

classpath*:dozer/dozer-mapping.xml

自动装配

至此,万事具备,你只需要自动装配mapper。

RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = {"classpath:spring/spring-dozer.xml"})

@TransactionConfiguration(defaultRollback = false)

public class DozerTest extends TestCase {

@Autowired

Mapper mapper;

@Test

public void testNotSameAttributeMapping() {

NotSameAttributeA src = new NotSameAttributeA();

src.setId(007);

src.setName("邦德");

src.setDate(new Date());

NotSameAttributeB desc = mapper.map(src, NotSameAttributeB.class);

Assert.assertNotNull(desc);

}

}

运行一下单元测试,绿灯通过。

Dozer支持的数据类型转换

Dozer可以自动做数据类型转换。当前,Dozer支持以下数据类型转换(都是双向的)

Primitive to Primitive Wrapper

原型(int、long等)和原型包装类(Integer、Long)

Primitive to Custom Wrapper

原型和定制的包装

Primitive Wrapper to Primitive Wrapper

原型包装类和包装类

Primitive to Primitive

原型和原型

Complex Type to Complex Type

复杂类型和复杂类型

String to Primitive

字符串和原型

String to Primitive Wrapper

字符串和原型包装类

String to Complex Type if the Complex Type contains a String constructor

字符串和有字符串构造器的复杂类型(类)

String to Map

字符串和Map

Collection to Collection

集合和集合

Collection to Array

集合和数组

Map to Complex Type

Map和复杂类型

Map to Custom Map Type

Map和定制Map类型

Enum to Enum

枚举和枚举

Each of these can be mapped to one another: java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, java.util.Calendar, java.util.GregorianCalendar

这些时间相关的常见类可以互换:java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, java.util.Calendar, java.util.GregorianCalendar

String to any of the supported Date/Calendar Objects.

字符串和支持Date/Calendar的对象

Objects containing a toString() method that produces a long representing time in (ms) to any supported Date/Calendar object.

如果一个对象的toString()方法返回的是一个代表long型的时间数值(单位:ms),就可以和任何支持Date/Calendar的对象转换。

Dozer的映射配置

在前面的简单例子中,我们体验了一把Dozer的映射流程。但是两个类进行映射,有很多复杂的情况,相应的,你也需要一些更复杂的配置。

Dozer有三种映射配置方式:

注解方式

API方式

XML方式

用注解来配置映射

Dozer 5.3.2版本开始支持注解方式配置映射(只有一个注解:@Mapping)。可以应对一些简单的映射处理,复杂的就玩不转了。

看一下@Mapping的声明就可以知道,这个注解只能用于元素和方法。

@Retention(RetentionPolicy.RUNTIME)

@Target({ElementType.FIELD, ElementType.METHOD})

public @interface Mapping {

String value() default "";

}

让我们来试试吧:

TargetBean.java

public class SourceBean {

private Long id;

private String name;

@Mapping("binaryData")

private String data;

@Mapping("pk")

public Long getId() {

return this.id;

}

//其余getter/setter方法略

}

TargetBean.java

public class TargetBean {

private String pk;

private String name;

private String binaryData;

//getter/setter方法略

}

定义了两个相互映射的Java类,只需要在源类中用@Mapping标记和目标类中对应的属性就可以了。

@Test

public void testAnnotationMapping() {

SourceBean src = new SourceBean();

src.setId(7L);

src.setName("邦德");

src.setData("00000111");

TargetBean desc = mapper.map(src, TargetBean.class);

Assert.assertNotNull(desc);

}

测试一下,绿灯通过。

官方文档说,虽然当前版本(文档的版本对应Dozer 5.5.1)仅支持@Mapping,但是在未来的发布版本会提供其他的注解功能,那就敬请期待吧(再次吐槽一下:一年多没更新了)。

用API来配置映射

个人觉得这种方式比较麻烦,不推荐,也不想多做介绍,就是这么任性。

用XML来配置映射

需要强调的是:如果两个类的所有属性都能很好的互转,可以你中有我,我中有你,不分彼此,那么就不要画蛇添足的在xml中去声明映射规则了。

属性名不同时的映射(Basic Property Mapping)

Dozer会自动映射属性名相同的属性,所以不必添加在xml文件中。

one

onePrime

字符串和日期映射(String to Date Mapping)

字符串在和日期进行映射时,允许用户指定日期的格式。

格式的设置分为三个作用域级别:

属性级别

对当前属性有效(这个属性必须是日期字符串)

dateString

dateObject

类级别

对这个类中的所有日期相关的属性有效

org.dozer.vo.TestObject

org.dozer.vo.TestObjectPrime

dateString

dateObject

全局级别

对整个文件中的所有日期相关的属性有效。

MM/dd/yyyy HH:mm

org.dozer.vo.TestObject

org.dozer.vo.TestObjectPrime

dateString

dateObject

集合和数组映射(Collection and Array Mapping)

Dozer可以自动处理以下类型的双向转换。

List to List

List to Array

Array to Array

Set to Set

Set to Array

Set to List

使用hint

如果使用泛型或数组,没有必要使用hint。

如果不使用泛型或数组。在处理集合或数组之间的转换时,你需要用hint指定目标列表的数据类型。

若你不指定hint,Dozer将认为目标集合和源集合的类型是一致的。

使用Hints的范例:

hintList

hintList

org.dozer.vo.TheFirstSubClassPrime

累计映射和非累计映射(Cumulative vs. Non-Cumulative List Mapping)

如果你要转换的目标类已经初始化,你可以选择让Dozer添加或更新对象到你的集合中。

而这取决于relationship-type配置,默认是累计。

它的设置有作用域级别:

全局级

non-cumulative

类级别

属性级别

hintList

hintList

org.dozer.vo.TheFirstSubClass

org.dozer.vo.TheFirstSubClassPrime

移动孤儿(Removing Orphans)

这里的孤儿是指目标集合中存在,但是源集合中不存在的元素。

你可以使用remove-orphans开关来选择是否移除这样的元素。

srcList

destList

深度映射(Deep Mapping)

所谓深度映射,是指允许你指定属性的属性(比如一个类的属性本身也是一个类)。举例来说

Source.java

public class Source {

private long id;

private String info;

}

Dest.java

public class Dest {

private long id;

private Info info;

}

public class Info {

private String content;

}

映射规则

org.zp.notes.spring.common.dozer.vo.Source

org.zp.notes.spring.common.dozer.vo.Dest

info

info.content

排除属性(Excluding Fields)

就像任何团体都有捣乱分子,类之间转换时也有想要排除的因子。

如何在做类型转换时,自动排除一些属性,Dozer提供了几种方法,这里只介绍一种比较通用的方法。

更多详情参考官网。

field-exclude可以排除不需要映射的属性。

fieldToExclude

fieldToExclude

单向映射(One-Way Mapping)

注:本文的映射方式,无特殊说明,都是双向映射的。

有的场景可能希望转换过程不可逆,即单向转换。

单向转换可以通过使用one-way来开启

类级别

org.dozer.vo.TestObjectFoo

org.dozer.vo.TestObjectFooPrime

oneFoo

oneFooPrime

属性级别

org.dozer.vo.TestObjectFoo2

org.dozer.vo.TestObjectFooPrime2

oneFoo2

oneFooPrime2

oneFoo3.prime

oneFooPrime3

全局配置(Global Configuration)

全局配置用来设置全局的配置信息。此外,任何定制转换都是在这里定义的。

全局配置都是可选的。

表示日期格式

错误处理开关

通配符

裁剪字符串开关

MM/dd/yyyy HH:mm

true

true

false

org.dozer.vo.TestCustomConverterObject

another.type.to.Associate

全局配置的作用是帮助你少配置一些参数,如果个别类的映射规则需要变更,你可以mapping中覆盖它。

覆盖的范例如下

定制转换(Custom Converters)

如果Dozer默认的转换规则不能满足实际需要,你可以选择定制转换。

定制转换通过配置XML来告诉Dozer如何去转换两个指定的类。当Dozer转换这两个指定类的时候,会调用你的映射规则去替换标准映射规则。

为了让Dozer识别,你必须实现org.dozer.CustomConverter接口。否则,Dozer会抛异常。

具体做法:

(1) 创建一个类实现org.dozer.CustomConverter接口。

public class TestCustomConverter implements CustomConverter {

public Object convert(Object destination, Object source,

Class destClass, Class sourceClass) {

if (source == null) {

return null;

}

CustomDoubleObject dest = null;

if (source instanceof Double) {

// check to see if the object already exists

if (destination == null) {

dest = new CustomDoubleObject();

} else {

dest = (CustomDoubleObject) destination;

}

dest.setTheDouble(((Double) source).doubleValue());

return dest;

} else if (source instanceof CustomDoubleObject) {

double sourceObj =

((CustomDoubleObject) source).getTheDouble();

return new Double(sourceObj);

} else {

throw new MappingException("Converter TestCustomConverter "

+ "used incorrectly. Arguments passed in were:"

+ destination + " and " + source);

}

}

(2) 在xml中引用定制的映射规则

引用定制的映射规则也是分级的,你可以酌情使用。

全局级

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://dozer.sourceforge.net

http://dozer.sourceforge.net/schema/beanmapping.xsd">

org.dozer.vo.CustomDoubleObject

java.lang.Double

type="org.dozer.converters.TestCustomHashMapConverter" >

org.dozer.vo.TestCustomConverterHashMapObject

org.dozer.vo.TestCustomConverterHashMapPrimeObject

属性级

org.dozer.vo.SimpleObj

org.dozer.vo.SimpleObjPrime2

"org.dozer.converters.TestCustomConverter">

field1

field1Prime

映射的继承(Inheritance Mapping)

Dozer支持映射规则的继承机制。

属性如果有着相同的名字则不需要在xml中配置,除非使用了hint

我们来看一个例子

org.dozer.vo.SuperClass

org.dozer.vo.SuperClassPrime

superAttribute

superAttr

org.dozer.vo.SubClass

org.dozer.vo.SubClassPrime

attribute

attributePrime

org.dozer.vo.SubClass2

org.dozer.vo.SubClassPrime2

attribute2

attributePrime2

在上面的例子中SubClass、SubClass2是SuperClass的子类;

SubClassPrime和SubClassPrime2是SuperClassPrime的子类。

superAttribute和superAttr的映射规则会被子类所继承,所以不必再重复的在子类中去声明。

参考

java dozer数组_Dozer 使用小结相关推荐

  1. java中数组赋值方法

    Java中数组赋值方法,以及为什么不能使用a = b //这里定义两个长度相同的数组,其中数组二为空 int[] arr1 = new int[]{1,2,3,4,5,6,0,0,0,0}; int[ ...

  2. java中数组的复制

    数组复制使我们在编程过程中经常要使用到的,在java中数组复制我们大概能够分为两种,一种是引用复制,还有一种就是深度复制(复制后两个数组互不相干). 以下我们就通过測试的方法来具体看看什么是引用复制和 ...

  3. Java输出数组中最长递增子序列的代码

    下面内容是关于Java输出数组中最长递增子序列的内容,希望对大伙有较大用途. package com.wzs;import java.util.ArrayList; import java.util. ...

  4. Java中getResourceAsStream的用法小结

    2019独角兽企业重金招聘Python工程师标准>>> Java中getResourceAsStream的用法小结 一.Java中的getResourceAsStream主要有以下三 ...

  5. Java中数组以及集合

    2019独角兽企业重金招聘Python工程师标准>>> java中数组: 数组在Java里是一种特殊类型,有别于普通的"类的实例"的对象.但实际数组也是一种对象类 ...

  6. Java的数组集合概括

    Java的数组集合概括 Collection 1.List(存储有序,有索引,可以重复) 1.1.ArrayList 底层是数组实现的,线程不安全,查找和修改快,增删比较慢 1.2.LinkedLis ...

  7. 十六、深入Java的数组(下篇)

    @Author:Runsen @Date:2020/5/23 本专栏是付费学Java专栏,今天我们继续来说一下Java的数组. 文章目录 二维数组 获取长度 遍历 排序 练习 前面已经讲过了一维数组的 ...

  8. 十五、深入Java的数组(上篇)

    @Author:Runsen @Date:2020/5/23 本专栏是付费学Java专栏,今天我们来说一下Java的数组. 数组是相同类型的变量的集合,所有元素的类型都一样. 文章目录 创建使用数组 ...

  9. Java中数组的定义,怎么发现那个方括号放在变量名前或者后都是正确的?

    int array[]= new int[3]; int[] array= new int[3]; 我运行了都正确?? Java的数组定义支持两种格式: int[] a和int a[] 前者是Java ...

最新文章

  1. GIT之旅【第一篇】
  2. 学习JavaScript 的必备
  3. C 数据结构之十大排序
  4. Spring MVC请求处理流程
  5. $_SERVER['SCRIPT_NAME']
  6. 【bzoj3576】 Hnoi2014—江南乐
  7. python语法_元组
  8. Xshell免密登录
  9. iOS 模拟器设置输入中文
  10. JAVA计算机毕业设计多媒体素材管理系统Mybatis+系统+数据库+调试部署
  11. 银河麒麟V10(Kylin Linux V10)之MySQL编译安装
  12. mysql中提取2015年10月数据_2015年10月自考互联网数据库(00911)试题及答案解析与评分标准 (1)...
  13. 创建OpenGL Context(WGL)
  14. 【LoRaWan】节点端(一)--SX1278介绍
  15. C#面向对象编程的学习笔记
  16. Windows10彻底卸载VMWare虚拟机
  17. 1000瓶水和1瓶毒水还有10只老鼠
  18. 好用的前端组件-颜色选择器
  19. linux运行wordcount,hadoop运行第一个实例wordcount
  20. 查找数组中的重复元素

热门文章

  1. D - Armchairs(DP)
  2. 树莓派4B GPIO介绍及编程
  3. ​VRTK4.0使用总结(三)UI交互​
  4. Android Camera Flashlight控制
  5. input绑定的jedate日期控件的值改变时触发事件问题
  6. 四川计算机本科招生学校有哪些,四川2021年计算机学校里面都有哪些专业
  7. 众手机厂商都与高通结伴孤立华为,原因何在?
  8. Vue项目性能优化篇
  9. CIKM 2020:Deep Time-Aware Item Evolution Network for Click-Through Rate Prediction(时间感知的深度物品演化网络)
  10. 阿里云ACP考试报名、复习、备考经验与心得分享