简述
在项目中使用过不少Java Bean映射(Java Bean属性拷贝)类库,比如Apache和Spring的BeanUtils
,cglib
的BeanCopier
等。
Apache和Spring的BeanUtils
没有对list拷贝的内置支持,对属性不同类型的转换也缺乏默认的支持,需要做不少封装。
cglib
的BeanCopier
的API相对来说比较难使用,虽然速度极快,但需要做更多的封装,可读性不好。
综合下来,发现Orika
能较好的满足各项常见的Java Bean映射需求。
使用实例
在实际使用中,通常可以把Orika
封装成一个静态工具类,示例如下:
public class BeanMapperUtils {
private static final DefaultMapperFactory mapperFactory ;
private static final MapperFacade mapper;
static {
mapperFactory = new DefaultMapperFactory.Builder().build();
mapper = mapperFactory.getMapperFacade();
}
public static <S, D> D map(S s, Class<D> aClass) {
return mapper.map(s, aClass);
}
public static <S, D> List<D> mapAsList(Iterable<S> iterable, Class<D> aClass) {
return mapper.mapAsList(iterable, aClass);
}
}
MapperFactory
和MapperFacade
都是线程安全的,可以使用单例模式。详情可参考官方文档的Use the MapperFactory as a singleton
章节。
静态工具类的方法使用委托模式,可以根据需求,只委托一些常用的方法。
示例实体类:
public class Customer {
private Long id;
private String name;
private Date birthday;
//省略 getter setter...
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", name='" + name + '\'' +
", birthday=" + birthday +
'}';
}
}
public class CustomerDTO {
private Long customerId;
private String name;
private String birthday;
//省略 getter setter...
@Override
public String toString() {
return "CustomerDTO{" +
"customerId=" + customerId +
", name='" + name + '\'' +
", birthday='" + birthday + '\'' +
'}';
}
}
常用简单示例
@Test
public void commonBeanMapperTest(){
Customer c = new Customer();
c.setName("foo1");
CustomerDTO dto = BeanMapperUtils.map(c, CustomerDTO.class);
Assert.assertEquals(dto.getName(), c.getName());
System.out.println(c.getName());
}
结果没有异常,输出为:foo1
。
List转换示例
@Test
public void listMapperTest(){
Customer c = new Customer();
c.setName("foo1");
Customer c2 = new Customer();
c2.setName("foo2");
ArrayList<Customer> list = new ArrayList<>();
list.add(c);
list.add(c2);
List<CustomerDTO> dtoList = BeanMapperUtils.mapAsList(list, CustomerDTO.class);
System.out.println(list);
System.out.println(dtoList);
}
输出结果:
[Customer{id=null, name='foo1', birthday=null}, Customer{id=null, name='foo2', birthday=null}]
[CustomerDTO{customerId=null, name='foo1', birthday='null'}, CustomerDTO{customerId=null, name='foo2', birthday='null'}]
日期转换示例
Date与String之间的互转,需要注册一个的转换器,可以在初始化MapperFactory
时注册全局转换器:
mapperFactory.getConverterFactory().registerConverter(new DateToStringConverter("yyyy-MM-dd HH:mm:ss"));
DateToStringConverter
为内置的双向转换器,可配置时间格式,也可以自定义转换器,这里使用内置转换器。示例:
public void dateMapperTest(){
Customer c = new Customer();
c.setBirthday(new Date());
CustomerDTO cdto = new CustomerDTO();
cdto.setBirthday("2019-12-12 08:00:00");
CustomerDTO dto = BeanMapperUtils.map(c, CustomerDTO.class);
System.out.println(c.getBirthday());
System.out.println(dto.getBirthday());
Customer customer = BeanMapperUtils.map(cdto, Customer.class);
System.out.println(customer.getBirthday());
System.out.println(cdto.getBirthday());
}
输出结果:
Sat Dec 07 16:21:58 CST 2019
2019-12-07 16:21:58
Thu Dec 12 08:00:00 CST 2019
2019-12-12 08:00:00
属性名不一致的情况的转换示例
属性名不一致的情况,需要注册转换类的属性名映射,以在初始化MapperFactory
时注册:
mapperFactory.classMap(Customer.class, CustomerDTO.class)
.field("id", "customerId")
.byDefault()
.register();
field
方法可以注册多个属性名的映射。转换示例:
@Test
public void fieldMapperTest(){
Customer c = new Customer();
c.setId(666L);
CustomerDTO dto = BeanMapperUtils.map(c, CustomerDTO.class);
System.out.println(c.getId());
System.out.println(dto.getCustomerId());
}
输出结果:
666
666
评论
发表评论