相信大家对于对象复制再熟悉不过了,基本上使用的大多都是Apache的BeanUtils,或者是Spring的BeanUtils,今天我们来介绍一下Orika。

要使用Orika很简单,只需要简单四步:

1.引入依赖

<dependency><groupId>ma.glasnost.orika</groupId><artifactId>orika-core</artifactId><version>1.5.4</version>
</dependency>

2.构造一个MapperFactory

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

3.注册字段映射

mapperFactory.classMap(SourceClass.class, TargetClass.class)  .field("firstName", "givenName").field("lastName", "sirName").byDefault().register();

字段名在两个实体不一致时可以通过.field()方法进行映射,如果字段名都一样则可省略,byDefault()方法用于注册名称相同的属性,如果不希望某个字段参与映射,可以使用exclude方法。

4.进行映射

MapperFacade mapper = mapperFactory.getMapperFacade();
SourceClass source = new SourceClass();
// set some field values
...
// map the fields of 'source' onto a new instance of PersonDest
TargetClass target = mapper.map(source, TargetClass.class);

经过上面四步我们就完成了SourceClass到TargetClass的转换。至于Orika的其他使用方法大家可以参考 http://orika-mapper.github.io/orika-docs/index.html

另外之前在某个博客上看到过有位好心人提供了一个Orika的util,今天也分享一下。

public class OrikaUtils {private static final MapperFactory FACTORY = new DefaultMapperFactory.Builder().build();/*** 缓存实例集合*/private static final Map<String, MapperFacade> CACHE_MAPPER = new ConcurrentHashMap<>();private final MapperFacade mapper;public OrikaUtils(MapperFacade mapper) {this.mapper = mapper;}/*** 转换实体函数* @param sourceEntity 源实体* @param targetClass  目标类对象* @param refMap       配置源类与目标类不同字段名映射* @param <S>          源泛型* @param <T>          目标泛型* @return 目标实体*/public static <S, T> T convert(S sourceEntity, Class<T> targetClass, Map<String, String> refMap) {if (sourceEntity == null) {return null;}return classMap(sourceEntity.getClass(), targetClass, refMap).map(sourceEntity, targetClass);}/*** 转换实体函数** @param sourceEntity 源实体* @param targetClass  目标类对象* @param <S>          源泛型* @param <T>          目标泛型* @return 目标实体*/public static <S, T> T convert(S sourceEntity, Class<T> targetClass) {return convert(sourceEntity, targetClass, null);}/*** 转换实体集合函数** @param sourceEntityList 源实体集合* @param targetClass      目标类对象* @param refMap           配置源类与目标类不同字段名映射* @param <S>              源泛型* @param <T>              目标泛型* @return 目标实体集合*/public static <S, T> List<T> convertList(List<S> sourceEntityList, Class<T> targetClass, Map<String, String> refMap) {if (sourceEntityList == null) {return null;}if (sourceEntityList.size() == 0) {return new ArrayList<>(0);}return classMap(sourceEntityList.get(0).getClass(), targetClass, refMap).mapAsList(sourceEntityList, targetClass);}/*** 转换实体集合函数** @param sourceEntityList 源实体集合* @param targetClass      目标类对象* @param <S>              源泛型* @param <T>              目标泛型* @return 目标实体集合*/public static <S, T> List<T> convertList(List<S> sourceEntityList, Class<T> targetClass) {return convertList(sourceEntityList, targetClass, null);}/*** 注册属性* @param source 源类* @param target 目标类* @param refMap 属性转换*/public static <V, P> void register(Class<V> source, Class<P> target,Map<String, String> refMap){if (CollectionUtils.isEmpty(refMap)) {FACTORY.classMap(source, target).byDefault().register();} else {ClassMapBuilder<V, P> classMapBuilder = FACTORY.classMap(source, target);refMap.forEach(classMapBuilder::field);classMapBuilder.byDefault().register();}}/*** 属性名称一致可用* @param source 源数据* @param target 目标对象* @return OrikaUtils*/private static <V, P> OrikaUtils classMap(Class<V> source, Class<P> target) {return classMap(source, target, null);}/*** 属性名称不一致可用** @param source 原对象* @param target 目标对象* @return OrikaUtils*/private static synchronized <V, P> OrikaUtils classMap(Class<V> source, Class<P> target, Map<String, String> refMap) {String key = source.getCanonicalName() + ":" + target.getCanonicalName();if (CACHE_MAPPER.containsKey(key)) {return new OrikaUtils(CACHE_MAPPER.get(key));}register(source,target,refMap);MapperFacade mapperFacade = FACTORY.getMapperFacade();CACHE_MAPPER.put(key, mapperFacade);return new OrikaUtils(mapperFacade);}/*** Orika复制对象* @param source 源数据* @param target 目标对象* @return target*/private <V, P> P map(V source, Class<P> target) {return mapper.map(source, target);}/*** 复制List* @param source 源对象* @param target 目标对象* @return P*/private <V, P> List<P> mapAsList(List<V> source, Class<P> target) {return CollectionUtils.isEmpty(source) ? Collections.emptyList() : mapper.mapAsList(source, target);}}

该util也简单介绍一下
先准备两个实体类

public class Student {private String id;private String name;private String email;
}
public class Teacher {private String id;private String name;private String emailAddress;
}

UT1,基础实体映射

/*** 只拷贝相同的属性*/Student student = new Student("1","javadaily","jianzh5@163.com");Teacher teacher = OrikaUtils.convert(student, Teacher.class);System.out.println(teacher);

输出结果:
Teacher(id=1, name=javadaily, emailAddress=null)
此时由于属性名不一致,无法映射字段email。

UT2,实体映射 - 字段转换

/*** 拷贝不同属性*/Student student = new Student("1","javadaily","jianzh5@163.com");Map<String,String> refMap = new HashMap<>(1);//map key 放置 源属性,value 放置 目标属性refMap.put("email","emailAddress");Teacher teacher = OrikaUtils.convert(student, Teacher.class, refMap);System.out.println(teacher);

输出结果:
Teacher(id=1, name=javadaily, emailAddress=jianzh5@163.com)
此时由于对字段做了映射,可以将email映射到emailAddress。注意这里的refMap中key放置的是源实体的属性,而value放置的是目标实体的属性,不要弄反了。

UT3,基础集合映射

/*** 只拷贝相同的属性集合*/Student student1 = new Student("1","javadaily","jianzh5@163.com");Student student2 = new Student("2","JAVA日知录","jianzh5@xxx.com");List<Student> studentList = Lists.newArrayList(student1,student2);List<Teacher> teacherList = OrikaUtils.convertList(studentList, Teacher.class);System.out.println(teacherList);

输出结果:

[Teacher(id=1, name=javadaily, emailAddress=null), Teacher(id=2, name=JAVA日知录, emailAddress=null)]
此时由于属性名不一致,集合中无法映射字段email。

UT4,集合映射 - 字段映射

/*** 映射不同属性的集合*/Student student1 = new Student("1","javadaily","jianzh5@163.com");Student student2 = new Student("2","JAVA日知录","jianzh5@xxx.com");List<Student> studentList = Lists.newArrayList(student1,student2);Map<String,String> refMap = new HashMap<>(2);//map key 放置 源属性,value 放置 目标属性refMap.put("email","emailAddress");List<Teacher> teacherList = OrikaUtils.convertList(studentList, Teacher.class,refMap);System.out.println(teacherList);

输出结果:

[Teacher(id=1, name=javadaily, emailAddress=jianzh5@163.com), Teacher(id=2, name=JAVA日知录, emailAddress=jianzh5@xxx.com)]

也可以通过这样映射:

Map<String,String> refMap = new HashMap<>(2);
refMap.put("email","emailAddress");
List<Teacher> teacherList = OrikaUtils.classMap(Student.class,Teacher.class,refMap).mapAsList(studentList,Teacher.class);

UT5,集合与实体映射

有时候我们需要将集合数据映射到实体中,如Person类

public class Person {private List<String> nameParts;
}

现在需要将Person类nameParts的值映射到Student中,可以这样做

/*** 数组和List的映射*/Person person = new Person();person.setNameParts(Lists.newArrayList("1","javadaily","jianzh5@163.com"));Map<String,String> refMap = new HashMap<>(2);//map key 放置 源属性,value 放置 目标属性refMap.put("nameParts[0]","id");refMap.put("nameParts[1]","name");refMap.put("nameParts[2]","email");Student student = OrikaUtils.convert(person, Student.class,refMap);System.out.println(student);

输出结果:

Student(id=1, name=javadaily, email=jianzh5@163.com)

UT6,类类型映射

有时候我们需要类类型对象映射,如BasicPerson类

@Data
public class BasicPerson {private Student student;
}

现在需要将BasicPerson映射到Teacher

/*** 类类型映射*/BasicPerson basicPerson = new BasicPerson();Student student = new Student("1","javadaily","jianzh5@163.com");basicPerson.setStudent(student);Map<String,String> refMap = new HashMap<>(2);//map key 放置 源属性,value 放置 目标属性refMap.put("student.id","id");refMap.put("student.name","name");refMap.put("student.email","emailAddress");Teacher teacher = OrikaUtils.convert(basicPerson, Teacher.class,refMap);System.out.println(teacher);

输出结果:

Teacher(id=1, name=javadaily, emailAddress=jianzh5@163.com)

UT7,多重映射

有时候我们会遇到多重映射,如将StudentGrade映射到TeacherGrade

@Data
public class StudentGrade {private String studentGradeName;private List<Student> studentList;
}@Data
public class TeacherGrade {private String teacherGradeName;private List<Teacher> teacherList;
}

这种场景稍微复杂,Student与Teacher的属性有email字段不相同,需要做转换映射;StudentGrade与TeacherGrade中的属性也需要映射。

/*** 一对多映射*/Student student1 = new Student("1","javadaily","jianzh5@163.com");Student student2 = new Student("2","JAVA日知录","jianzh5@xxx.com");List<Student> studentList = Lists.newArrayList(student1,student2);StudentGrade studentGrade = new StudentGrade();studentGrade.setStudentGradeName("硕士");studentGrade.setStudentList(studentList);Map<String,String> refMap1 = new HashMap<>(1);//map key 放置 源属性,value 放置 目标属性refMap1.put("email","emailAddress");OrikaUtils.register(Student.class,Teacher.class,refMap1);Map<String,String> refMap2 = new HashMap<>(2);//map key 放置 源属性,value 放置 目标属性refMap2.put("studentGradeName", "teacherGradeName");refMap2.put("studentList", "teacherList");TeacherGrade teacherGrade = OrikaUtils.convert(studentGrade,TeacherGrade.class,refMap2);System.out.println(teacherGrade);

多重映射的场景需要根据情况调用OrikaUtils.register()注册字段映射。
输出结果:

TeacherGrade(teacherGradeName=硕士, teacherList=[Teacher(id=1, name=张三, emailAddress=zhangsan@163.com), Teacher(id=2, name=李四, emailAddress=zhangsan@xxx.com)])

UT8,MyBaits plus分页映射

如果你使用的是mybatis的分页组件,可以这样转换

public IPage<UserDTO> selectPage(UserDTO userDTO, Integer pageNo, Integer pageSize) {Page page = new Page<>(pageNo, pageSize);LambdaQueryWrapper<User> query = new LambdaQueryWrapper();if (StringUtils.isNotBlank(userDTO.getName())) {query.like(User::getKindName,userDTO.getName());}IPage<User> pageList = page(page,query);// 实体转换 SysKind转化为SysKindDtoMap<String,String> refMap = new HashMap<>(3);refMap.put("kindName","name");refMap.put("createBy","createUserName");refMap.put("createTime","createDate");return pageList.convert(item -> OrikaUtils.convert(item, UserDTO.class, refMap));
}

对象复制的另一种方法相关推荐

  1. c语言实现将两个文件复制到一个文件里_Python中复制文件的9种方法

    作者:小小程序员 链接:https://zhuanlan.zhihu.com/p/91277888 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. Python 中有 ...

  2. python复制文件的方法是_Python中复制文件的9种方法

    Python 中有许多"开盖即食"的模块(比如 os,subprocess 和 shutil)以支持文件 I/O 操作.在这篇文章中,你将会看到一些用 Python 实现文件复制的 ...

  3. Python复制文件的9种方法

    以下是演示"如何在Python中复制文件"的九种方法. 1.shutil copyfile()方法 2.shutil copy()方法 3.shutil copyfileobj() ...

  4. python os复制文件_用Python复制文件的九种方法

    以下是演示"如何在Python中复制文件"的九种方法. shutil copyfile()方法 shutil copy()方法 shutil copyfileobj()方法 shu ...

  5. 利用Python复制文件的9种方法总结

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取 python免费学习资 ...

  6. Python 复制文件的 9 种方法

    用 Python 复制文件的 9 种方法具体是: shutil copyfile() 方法 shutil copy() 方法 shutil copyfileobj() 方法 shutil copy2( ...

  7. 两个对象数组去重的3种方法

    两个对象数组去重的3种方法 前言 问题描述 解决方案一 解决方案二 解决方案三 前言 前段时间写过JavaScript数组去重最简单的 4 种方案,里面的数组元素是基本类型.本文要讲的数组元素是对象, ...

  8. 对象深浅拷贝的四种方法

    对象深浅拷贝的四种方法 存在这么一个对象,对他进行深拷贝 var obj = {name: '法外狂徒张三',age: 24, say() {console.log('鱼跃此时海');}}; 浅拷贝 ...

  9. js 对象深拷贝、对象数组深拷贝的几种方法总结

    写前端的时候经常会遇到对象的拷贝,一般我们会用到深拷贝,深拷贝就是完完整整的将一个对象从内存中拷贝一份出来,放到另一块新开辟的内存中去.向下面这种赋值是浅拷贝,a.b都是对同一块内存进行引用,a.b哪 ...

最新文章

  1. 吴恩达新书《Machine Learning Yearning》手稿完工,现在全集免费下载!(附pdf下载)
  2. 计算机学科技术前沿:互联网上信息可信性的现状
  3. 漫画算法:5 分钟搞明白红黑树到底是什么?
  4. java怎么对用户做自定义模版打印_Printing tools 自定义模板打印的实现
  5. 计算机教学能力大赛实施报告模板,教学能力比赛教学实施报告现场汇报PPT模板-橙色主题.pptx...
  6. 快慢指针(Fast and Slow Pointers)
  7. 【深度学习】NLP|用GRU模型给周董写首歌
  8. 4_04_GLib库入门与实践_指针数组
  9. matlab eigs 求特征值函数
  10. PCL安装与配置(Windows10+VS2017 )
  11. 如何预防钓鱼邮件?S/MIME邮件证书来支招
  12. 十大工业设计公司是如何排名的?
  13. Oracle两行数据相减
  14. 大屏数据展示,5.5寸大屏幕手机更受消费者喜爱
  15. jQuery 实现动态粒子特效,太美了!!!
  16. 【JZOJ 5426】【NOIP2017提高A组集训10.25】摘Galo
  17. WebSestalt,好用的富集分析工具,介绍及使用教程
  18. matlab fpga 移植,使用MATLAB,Simulink以及基于模型的设计实现把电机控制算法移植到Zynq平台...
  19. Securify之旅1之TOD漏洞剖析
  20. 莫听穿林打叶声,2022年SSD行业回顾与展望

热门文章

  1. HarmonyOS智能座舱体验是怎样炼成的?立即查看
  2. [Err] 1366 - Incorrect string value: ‘\xE5\xBC\xA0\xE4\xB8\x89‘ for column ‘name‘ at row 1
  3. EMWIN 使用记录
  4. 关于质数的后代的解题
  5. 51单片机的入门知识(献给初学者最易懂的文章)
  6. http抓包分析技巧总结
  7. 转载:文本编辑器 UltraEdit/EmEditor/EditPlus/AptEdit 之超级评测
  8. linux networkmanager 防火墙,Linux下关闭防火墙与NetworkManager
  9. 关于SMR,IMR的调研
  10. 试图让伙伴理解自己——是人和大猩猩的核心区别