Appearance
Orika
1. 概述
Orika 是一个简单、快速的 JavaBean 拷贝框架,它能够递归地将数据从一个 JavaBean 复制到另一个 JavaBean,这在多层应用开发中是非常有用的。
官方使用指南:http://orika-mapper.github.io/orika-docs/index.html
2. 基本使用
2.1 Maven 项目增加依赖包
xml
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.5.4</version>
</dependency>
2.2 A 对象复制到 B 对象
java
User userA = new User().setId(1).setName("麻子哥");
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
User userB = mapperFactory.getMapperFacade().map(userA, User.class);
log.debug("userB - {}", userB);
上述代码中,MapperFactory
是映射工厂,用来定义转换规则(任何字段映射、注册转换器、自定义映射器、用于抽象/接口类型的具体类型)并生成 MapperFacade
;MapperFacade
是映射门面,进行对象转换的实际执行器。
2.3 A 集合复制到 B 集合
java
List<User> userListA = Arrays.asList(new User().setId(1).setName("张三"));
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
List<User> userListB = mapperFactory.getMapperFacade().mapAsList(userListA, User.class);
log.debug("userListB - {}", userListB);
3. 高级用法
3.1 对象属性名称不一致
java
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(User.class, UserVo.class)
.field("name", "userName")
.field("age", "ageOne")
.exclude("secretKey")
.byDefault()
.register();
UserVo userVo = mapperFactory.getMapperFacade().map(userA, UserVo.class);
classMap(A, B)
方法定义了相互转换的类,不分源对象和目标对象。field("name", "fullName")
表示 A、B 类中 name 和 fullName 字段的双向映射,如果只想要 A 对象 name 赋值给 B 对象的 fullName,则需要使用fieldAToB("fullName", "name")
。byDefault()
方法表示当 A、B 对象的字段名一致时,自动赋值,如果没有该方法则不会赋值。exclude("secretKey")
显示地排除了 secretKey 字段的赋值。
3.2 集合中属性名称不一致
同对象属性名称不一致的处理,只不过最后一行代码中调用的 map()
方法替换为 mapAsList()
。
java
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(User.class, UserVo.class)
.field("name", "userName")
.field("age", "ageOne")
.exclude("secretKey")
.byDefault()
.register();
List<UserVo> userVos = mapperFactory.getMapperFacade().mapAsList(userListA, UserVo.class);
3.3 指定需要使用的特定构造函数
orika 提供了 constructorA
和 constructorB
方法用于使用有参构造器生成新类,例如下面的代码中在生成 A 对象时优先使用构造方法 public BasicPerson(Long id, String name)
完成。
java
mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
.constructorA("id", "name")
//...
.register();
3.4 映射嵌套字段
嵌套属性可以使用“.”来引用,例如 BasicPerson
对象中的姓名是一个对象 private Name name
,可以使用下面语法进行字段值的转换。
java
mapperFactory.classMap(BasicPerson.class, BasicPersonDto.class)
.field("name.first", "firstName")
.register();
3.5 使用 BoundMapperFacade
如果需要频繁进行 AB 对象的转换,可以使用特定的 BoundMapperFacade
以追求更好的性能。
java
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
// 设置该facade是由ApproveSubmitRequest向ApprovalEntry转换
BoundMapperFacade<ApproveSubmitRequest, ApprovalEntry> facade = mapperFactory
.getMapperFacade(ApproveSubmitRequest.class, ApprovalEntry.class);
// 进行字段映射
ApprovalEntry entry = facade.map(request);
3.6 自定义转换规则
有时候,我们不是要简单的转换,比如说我们希望转换后的 brand 统一变成大写,那么这个时候,我们就可以自定义转换规则做些额外的处理。
java
OrderDTO orderDTO = new OrderDTO("1", "kfc", "南京路", "666");
DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
// 如果存在字段名不一致,手动告诉orika他们之间的映射关系
mapperFactory.classMap(OrderDTO.class,OrderDO.class)
.field("orderId","id")
.field("mobile","phone")
.field("orderItem.itemId","orderItem.id")
.byDefault()
// 自定义我们的转换规则
.customize(new CustomMapper<OrderDTO, OrderDO>() {
@Override
public void mapAtoB(OrderDTO orderDTO, OrderDO orderDO, MappingContext context) {
// 将品牌转换成大写
orderDO.setBrand(orderDTO.getBrand().toUpperCase(Locale.ROOT));
}
})
.register();
OrderDO order = mapperFactory.getMapperFacade().map(orderDTO, OrderDO.class);
System.out.println(order);