基本操作
-
创建一个
MapperFacadeMapperFacade mapperFacade = new Builder().build().getMapperFacade(); -
使用该
MapperFacade对象进行任意的Bean转换ApproveSubmitRequest request = getRequest(); ApprovalEntry entry = mapperFacade.map(request, ApprovalEntry.class);
基本概念
MapperFactory: 映射工厂,用来定义转换规则(任何字段映射、注册转换器、自定义映射器、用于抽象/接口类型的具体类型)并生成MapperFacade
MapperFacade: 映射门面,进行对象转换的实际执行器
使用fluent风格的ClassMapBuilder API的声明性映射配置
基本的字段映射
转换规则是对MapperFactory对象定义的,以下面转换的规则为例
mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
.field("name", "fullName")
.field("age", "currentAge")
.exclude("secretKey")
.byDefault()
.register();
classMap(A, B)方法定义了相互转换的类,不分源对象和目标对象。field("name", "fullName")表示AB类中name和fullName字段的双向映射,如果只想要A对象name赋值给B对象的fullName,则需要使用fieldAToB("fullName", "name")。byDefault()方法表示当AB对象的字段名一致时,自动赋值,如果没有该方法则不会赋值。exclude("secretKey")显示地排除了secretKey字段的赋值。
指定要使用的特定构造函数
orika 提供了constructorA和constructorB方法用于使用有参构造器生成新类,例如下面的代码中在生成A对象时优先使用构造方法public BasicPerson(Long id, String name)完成
mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
.constructorA("id", "name")
...
.register();
数组和列表的映射元素
BasicPerson对象中将姓名作为列表存储,第一个元素为firstName,第二个元素为lastName,对于列表或数组,可以使用下面的语法进行字段值的转换。
mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
.field("nameParts[0]", "firstName")
.field("nameParts[1]", "lastName")
.register();
映射嵌套字段
嵌套属性可以使用“.”来引用,例如BasicPerson中的姓名是一个对象private Name name,可以使用下面语法进行字段值的转换。
mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
.field("name.first", "firstName")
.register();
使用BoundMapperFacade以获得更好的性能
如果需要频繁进行AB对象的转换,可以使用特定的BoundMapperFacade以追求更好的性能
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
// 设置该facade是由ApproveSubmitRequest向ApprovalEntry转换
BoundMapperFacade<ApproveSubmitRequest, ApprovalEntry> facade = mapperFactory
.getMapperFacade(ApproveSubmitRequest.class, ApprovalEntry.class);
// 进行字段映射
ApprovalEntry entry = facade.map(request);
高级映射配置
空值映射
进行AB对象转换时,对于空值字段的处理,选择映射还是忽略根据场景的不同而不同。默认情况下orika 框架选择的策略是忽略。
ClassMap 级别
可以在ClassMap级别设置是否映射空值,例如下面在field1和fieldOne 转换前将其设置为“映射空值”,转换后再设置为“忽略空值”
mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
// 设置为映射空值
.mapNulls(true).mapNullsInReverse(true)
.field("field1", "fieldOne")
// 设置为忽略空值
.mapNulls(false).mapNullsInReverse(false)
.field("field2", "fieldTwo")
.byDefault()
.register();
FieldMap 级别
在FieldMap级别设置空值则使用fieldMap方法,指定某些字段的转换是“赋值”还是“忽略”。
mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
.mapNulls(false).mapNullsInReverse(false)
.fieldMap("field1", "fieldOne").mapNulls(true).mapNullsInReverse(true).add()
.field("field2", "fieldTwo")
.byDefault()
.register();
自定义单个 ClassMaps
使用 orika 框架提供的customize()方法可以自定义由AB对象的转换方法
mapperFactory.classMap(Source.class, Destination.class)
.customize(
new CustomMapper<Source, Destination>() {
@Override
public void mapAtoB(Source source, Destination dest,
MappingContext context) {
super.mapAtoB(source, dest, context);
}
@Override
public void mapBtoA(Destination approvalEntry, Source source,
MappingContext context) {
super.mapBtoA(dest, source, context);
}
}).register();
自定义转换器
Orika 框架支持注册自定义的转换器,支持在全局注册和字段级别的注册,例如我们定义一个如下的转换器,用于从DateTime转换到Date
public class JodaTimeToDateConverter extends CustomConverter<DateTime, Date> {
@Override
public Date convert(DateTime source, Type<? extends Date> destinationType,
MappingContext mappingContext) {
return source.toDate();
}
}
定义完转换器后支持在全局注册,如下面代码所示,应用到所有DateTime类型字段到Date类型字段应用转换器。
mapperFactory.getConverterFactory().registerConverter(new JodaTimeToDateConverter());
也可以在字段级别注册,如下面代码所示,仅对createTime字段应用转换器。
mapperFactory.getConverterFactory().registerConverter("createTime", new JodaTimeToDateConverter());
另外上述仅支持了DateTime转换到Date,可以继承BidirectionalConverter类以完成两个类型的双向转换,如下面代码所示
public class JodaTimeToDateConverter extends BidirectionalConverter<DateTime, Date> {
@Override
public Date convertTo(DateTime source, Type<Date> destinationType,
MappingContext mappingContext) {
return source.toDate();
}
@Override
public DateTime convertFrom(Date source, Type<DateTime> destinationType,
MappingContext mappingContext) {
return new DateTime(source);
}
}