Orika

前言

类复制工具有很多,比较常用的有 mapstruct、Spring BeanUtils、Apache BeanUtils、dozer 等,目前我所在的项目组中使用的是 mapstruct。在性能方面,mapstruct 毫无疑问是最优秀的,因为 mapstruct 是通过 getter、setter 方法来复制属性值的,而其它框架或多或少使用反射进行复制,这里也不再赘述。但是,mapstruct 也有它的不足之处,请看下面:

不知道大家使用 mapstruct 时,是否编写过类似如下的 java 表达式:

@Mapper
public interface SmsTemplateConverter { SmsTemplateConverter SMS_TEMPLATE_CONVERTER = Mappers.getMapper(SmsTemplateConverter.class); @Mappings({
// 这里只能通过全类名来调用静态方法,否则类无法注入到编译后的文件
@Mapping(target = "templateType", expression = "java(org.example.enums.SmsEnum.getTypeByCode(platformTemp.getTemplateType()))")
})
SmsCompanyTemplateVO toSmsCompanyTemplateVO(SmsCompanyTemplate companyTemp, SmsPlatformTemplate platformTemp);
}

我们不难发现,一旦这里的 org.example.enums.SmsEnum 全类名目录发生改变,此处的代码就会报错,因为这里的 expression 是字符串,在目录更改时,不能自动更改全类名路径(因为是字符串,不是真正的 java 代码,mapstruct 的 java 表达式是由代码生成器生成的,在编译后 target 目录下可以看到),等于是写死的,后期维护和扩展时会比较困难,因此我们项目中决定放弃 mapsruct。

在调研了众多类复制工具后,我选择了 Orika,并通过 demo 验证确实可行,在了解 Orika 前,不妨了解一下各个类复制工具的对比,如下图示:(图片源于网络,如有侵权,请联系删除)

使用示例

下面我会以一个基本示例和一个Date属性转String属性的示例来示范 Orika 的使用。

导入依赖

<!-- 类复制工具:orika -->
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.5.2</version><!-- or latest version -->
</dependency> <!-- hu-tool 工具包 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.16</version>
</dependency> <!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>

定义实体 Person 和 PersonDTO

Person实体:

import lombok.Data;
import java.util.Date; @Data
public class Person {
private String name; // 注意这个字段名是与 PersonDTO 相同的
private String age;
private Date birth;
}

PersonDTO实体:

import lombok.Data;

@Data
public class PersonDTO {
private String name;
private Integer dtoAge;
private String dtoBirth;
}

基本示例

简单用法一:

import ma.glasnost.orika.MapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.example.entity.Person;
import org.example.entity.PersonDTO; // MapperFacade
public class MapperFacadeMain {
public static void main(String[] args) {
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Person.class, PersonDTO.class)
.field("age", "dtoAge") // 属性名不同时的处理
.byDefault() // 未列举的属性自动匹配
.register();
Person person = new Person();
person.setAge("123"); // 字符串与数字可以互转
person.setName("张三");
MapperFacade mapper = mapperFactory.getMapperFacade(); // MapperFacade 的性能不如 BoundMapperFacade
PersonDTO personDTO = mapper.map(person, PersonDTO.class);
System.out.println(personDTO);
}
} // 输出 PersonDTO(name=张三, dtoAge=123, dtoBirth=null)

简单用法二:

import ma.glasnost.orika.BoundMapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.example.entity.Person;
import org.example.entity.PersonDTO; public class BoundMapperFacadeMain {
public static void main(String[] args) {
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
mapperFactory.classMap(Person.class, PersonDTO.class)
.field("age", "dtoAge")
.byDefault()
.register();
Person person = new Person();
person.setAge("456");
person.setName("李四");
BoundMapperFacade<Person, PersonDTO> boundMapper =
mapperFactory.getMapperFacade(Person.class, PersonDTO.class);
PersonDTO personDTO = boundMapper.map(person);
System.out.println(personDTO);
}
} // 输出 PersonDTO(name=李四, dtoAge=456, dtoBirth=null)

Date 转 String 示例

定义 converter:

import cn.hutool.core.date.DateTime;
import ma.glasnost.orika.CustomConverter;
import ma.glasnost.orika.MappingContext;
import ma.glasnost.orika.metadata.Type;
import java.util.Date; public class DateConverter extends CustomConverter<Date,String> { @Override
public String convert(Date date, Type<? extends String> type, MappingContext mappingContext) {
DateTime time = DateTime.of(date);
return time.toString("yyyy-MM-dd HH:mm:ss");
}
}

主函数:

import ma.glasnost.orika.BoundMapperFacade;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.converter.ConverterFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.example.converter.DateConverter;
import org.example.entity.Person;
import org.example.entity.PersonDTO;
import java.util.Date; public class MainB {
public static void main(String[] args) {
MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
ConverterFactory converterFactory = mapperFactory.getConverterFactory(); // 注册 converter
converterFactory.registerConverter("DateConverterId", new DateConverter()); // 这里给 DateConverter 设置一个 id 为 DateConverterId,如果不设置,则为全局注册
mapperFactory.classMap(Person.class, PersonDTO.class)
.field("age", "dtoAge")
.fieldMap("birth", "dtoBirth").converter("DateConverterId").add()
.byDefault()
.register();
Person person = new Person();
person.setAge("789");
person.setName("王五");
person.setBirth(new Date()); // 设置 Date
BoundMapperFacade<Person, PersonDTO> boundMapper =
mapperFactory.getMapperFacade(Person.class, PersonDTO.class);
PersonDTO personDTO = boundMapper.map(person);
System.out.println(personDTO);
}
} // 输出 PersonDTO(name=王五, dtoAge=789, dtoBirth=2021-11-29 20:34:21)

此时可以发现,自定义的转换器已经生效。

小结

不难发现,上面的 MapperFactory 在实际的项目开发中,应该定义为单例,由全局来共享一个 MapperFactory,官方文档中也有相关说明,感兴趣可以查看文档,以上就是有关 Orika 的分享,欢迎交流,共同进步。

更多用法

更多用法请参考官方文档:

文档地址:http://orika-mapper.github.io/orika-docs/index.html

Github:https://github.com/orika-mapper?language=html

笔记下载

此文章系原创,转载请附上链接,抱拳。

此文档提供 markdown 源文件下载,请去我的码云仓库进行下载。 下载文档

若本文对你有用,请不要忘记给我的点个 Star 哦!

Orika - 类复制工具的更多相关文章

  1. Mysql 复制工具(percona-toolkit)

    Mysql 复制工具 1.percona-toolkit简介 percona-toolkit是一组高级命令行工具的集合,用来执行各种通过手工执行非常复杂和麻烦的mysql和系统任务,这些任务包括: 检 ...

  2. ORM存储过程和实体类代码生成工具

    ORM存储过程和实体类生成工具 自己写的一个ORM框架的存储过程和实体类生成工具,具体界面如下: 操作步骤: 1.设置数据库连接: 2.选择要生成的表或视图: 3.选择要生成的存储过程类型: 4.如果 ...

  3. Dozer--第三方复制工具,哎哟,还不错!

    Dozer简单点说,就是拷贝工具,也是复制工具的意思,官方的解释是:Dozer is a Java Bean to Java Bean mapper that recursively copies d ...

  4. [软件推荐]快速文件复制工具(Limit Copy) V4.0 绿色版

    快速文件复制工具(Limit Copy)绿色版是一款智能变频超快复制绿色软件. 快速文件复制工具(Limit Copy)功能比较完善,除了文件复制还可以智能变频,直接把要复制的文件拖入窗口即可,无需手 ...

  5. Unity协程(Coroutine)管理类——TaskManager工具分享

    博客分类: Unity3D插件学习,工具分享 源码分析   Unity协程(Coroutine)管理类——TaskManager工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处 ...

  6. Unity多线程(Thread)和主线程(MainThread)交互使用类——Loom工具分享

    Unity多线程(Thread)和主线程(MainThread)交互使用类——Loom工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com ...

  7. 这个类复制文本文件FileCopy

    package JBJADV003; import java.io.File;import java.io.BufferedReader;import java.io.BufferedWriter;i ...

  8. c# 实体类生成工具

    一个简单生成c#实体类的工具 源代码下载

  9. ArcGIS 要素类平移工具-arcgis案例实习教程

    ArcGIS 要素类平移工具-arcgis案例实习教程 联系方式:谢老师,135-4855-4328,xiexiaokui#qq.com 目的:对整个要素类,按指定偏移距离,进行整体平移. 优点:使用 ...

随机推荐

  1. 2020.12.14--Codeforces Round #104 (Div.2)补题

    C - Lucky Conversion CodeForces - 146C Petya loves lucky numbers very much. Everybody knows that luc ...

  2. Intellij IDEA使用姿势

    Intellij IDEA 智能补全的 10 个姿势,太牛逼了.. Intellij Idea非常6的10个姿势

  3. 8.5(337)——树形dp

    将题目进行翻译,就是遍历二叉树算出最大权值,在遍历过程中,不能同时选择两个相连的节点. 第一种子问题的构造,是以爷爷--父亲--孙子的"三代"节点一同构造的,将最优子问题的结构定义 ...

  4. Go语言核心36讲(Go语言进阶技术六)--学习笔记

    12 | 使用函数的正确姿势 在前几期文章中,我们分了几次,把 Go 语言自身提供的,所有集合类的数据类型都讲了一遍,额外还讲了标准库的container包中的几个类型. 在几乎所有主流的编程语言中, ...

  5. [WPF] 在 Windows 11 中处理 WindowChrome 的圆角

    1. Windows 11 的圆角 在直角统治了微软的 UI 设计多年以后,微软突然把直角骂了一顿,说还是圆角好看,于是 Windows 11 随处都可看到圆角设计.Windows 11 使用 3 个 ...

  6. 最近公共祖先 牛客网 程序员面试金典 C++ Python

    最近公共祖先 牛客网 程序员面试金典 C++ Python 题目描述 有一棵无穷大的满二叉树,其结点按根结点一层一层地从左往右依次编号,根结点编号为1.现在有两个结点a,b.请设计一个算法,求出a和b ...

  7. Educational Codeforces Round 113 (Rated for Div. 2)题解

    \(A,B,C\)顺利签到,还是在\(D\)上面卡住了,之后在睡前还是想出来了,看来还是自己的思维不够敏捷和成熟... D. Inconvenient Pairs 简化题意,在一个直角坐标系中,有一些 ...

  8. nginx 支持https访问

    1,先确认nginx安装时已编译http_ssl模块. 就是执行nginx -V命令查看是否存在--with-http_ssl_module.如果没有,则需要重新编译nginx将该模块加入.yum安装 ...

  9. Linux安装部署Zabbix

    Zabbix 是一个企业级的分布式开源监控方案,能够监控各种网络参数以及服务器健康性和完整性的软件.Zabbix使用灵活的通知机制,允许用户为几乎任何事件配置基于邮件的告警.这样可以快速反馈服务器的问 ...

  10. 计算机网络漫谈之UDP和TCP

    计算机网络漫谈之传输层 咱们讨论了如果需要确定一个计算机上的不同网络程序(比如QQ和浏览器),需要端口的标识,但是IP头部和帧的头部都没有端口的标识字段,需要新的协议.和前面IP协议的实现套路一样,我 ...