性能高、上手快,实体类转换工具 MapStruct 到底有多强大

简介: 1.什么是MapStruct1.1 JavaBean 的困扰对于代码中 JavaBean之间的转换, 一直是困扰我很久的事情。在开发的时候我看到业务代码之间有很多的 JavaBean 之间的相互转化, 非常的影响观感,却又不得不存在。我后来想的一个办法就是通过反射,或者自己写很多的转换器。第一种通过反射的方法确实比较方便,但是现在无论是 BeanUtils, BeanCopier 等在使用反射的时候都会影响到性能。虽然我们可以进行反射信息的缓存来提高性能。但是像这种的话,需要类型和名称都一样才会进行映射,有很多时候,由于不同的团队之间使用的名词不一样,还是需要很多的手动 set/get

1.什么是MapStruct

1.1 JavaBean 的困扰

对于代码中 JavaBean之间的转换, 一直是困扰我很久的事情。在开发的时候我看到业务代码之间有很多的 JavaBean 之间的相互转化, 非常的影响观感,却又不得不存在。我后来想的一个办法就是通过反射,或者自己写很多的转换器。

第一种通过反射的方法确实比较方便,但是现在无论是 BeanUtils, BeanCopier 等在使用反射的时候都会影响到性能。虽然我们可以进行反射信息的缓存来提高性能。但是像这种的话,需要类型和名称都一样才会进行映射,有很多时候,由于不同的团队之间使用的名词不一样,还是需要很多的手动 set/get 等功能。

第二种的话就是会很浪费时间,而且在添加新的字段的时候也要进行方法的修改。不过,由于不需要进行反射,其性能是很高的。推荐:Java进阶视频资源

1.2 MapStruct 带来的改变

MapSturct 是一个生成类型安全,高性能且无依赖的 JavaBean 映射代码的注解处理器(annotation processor)。

  • 注解处理器
  • 可以生成 JavaBean 之间那的映射代码
  • 类型安全,高性能,无依赖性

2.MapStruct 入门

2.1 添加依赖

网络异常,图片无法展示
|

2.2 po类

网络异常,图片无法展示
|

2.3 dto类

网络异常,图片无法展示
|

2.4 创建转换接口

网络异常,图片无法展示
|

2.5 测试方法

网络异常,图片无法展示
|

2.6 运行效果

网络异常,图片无法展示
|

2.7 查看编译的class

底层通过自动取值赋值操作完成

网络异常,图片无法展示
|

3.MapStruct优点分析

3.1 性能高

这是相对反射来说的,反射需要去读取字节码的内容,花销会比较大。而通过 MapStruct 来生成的代码,其类似于人手写。速度上可以得到保证。

3.2 使用简单

如果是完全映射的,使用起来肯定没有反射简单。用类似 BeanUtils 这些工具一条语句就搞定了。但是,如果需要进行特殊的匹配(特殊类型转换,多对一转换等),其相对来说也是比较简单的。

基本上,使用的时候,我们只需要声明一个接口,接口下写对应的方法,就可以使用了。当然,如果有特殊情况,是需要额外处理的。推荐:Java进阶视频资源

3.3 代码独立

生成的代码是对立的,没有运行时的依赖。

3.4 易于 debug

在我们生成的代码中,我们可以轻易的进行 debug。

4.MapStruct使用案例

4.1 属性名称相同

在实现类的时候,如果属性名称相同,则会进行对应的转化。通过此种方式,我们可以快速的编写出转换的方法。(入门案例)

4.2 属性名不相同

属性名不相同,在需要进行互相转化的时候,则我们可以通过@Mapping 注解来进行转化。

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

  • source 需要转换的对接,通常是入参
  • target 转换的对接,通常是出参
  • ignore 忽略,默认false不忽略,需要忽略设置为true
  • defaultValue 默认值
  • expressions 可以通过表达式来构造一些简单的转化关系。虽然设计的时候想兼容很多语言,不过目前只能写Java代码。
@Mappings({
            @Mapping(source = "birthdate", target = "birth"),//属性名不一致映射
            @Mapping(target = "birthformat", expression = "java(org.apache.commons.lang3.time.DateFormatUtils.format(person.getBirthdate(),\"yyyy-MM-dd HH:mm:ss\"))"),//自定义属性通过java代码映射
    })
public PersonVo PersonToPersonVo(Person person);

这里用到演示了如何使用TimeAndFormat对time和format操作,这里必须要指定需要使用的Java类的完整包名,不然编译的时候不知道你使用哪个Java类,会报错。

网络异常,图片无法展示
|

网络异常,图片无法展示
|

4.3 转换非基础类型属性

如果subUser与subUserDto字段名称相同直接配置即可完成(对象类型,包括list)

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

4.4 Mapper 中使用自定义的转换

有时候,对于某些类型,无法通过代码生成器的形式来进行处理。那么, 就需要自定义的方法来进行转换。这时候,我们可以在接口(同一个接口,后续还有调用别的 Mapper 的方法)中定义默认方法(Java8及之后)。

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

只能存在一个default修饰的方法

网络异常,图片无法展示
|

网络异常,图片无法展示
|

4.5 多转一

我们在实际的业务中少不了将多个对象转换成一个的场景。MapStruct 当然也支持多转一的操作。推荐:Java进阶视频资源

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

4.5.1 遵循原则

  • 当多个对象中, 有其中一个为 null, 则会直接返回 null
  • 如一对一转换一样, 属性通过名字来自动匹配。因此, 名称和类型相同的不需要进行特殊处理
  • 当多个原对象中,有相同名字的属性时,需要通过 @Mapping 注解来具体的指定, 以免出现歧义(不指定会报错)。如上面的 name

属性也可以直接从传入的参数来赋值

网络异常,图片无法展示
|

4.6 更新 Bean 对象

有时候,我们不是想返回一个新的 Bean 对象,而是希望更新传入对象的一些属性。这个在实际的时候也会经常使用到。

网络异常,图片无法展示
|

网络异常,图片无法展示
|

4.7 map映射

网络异常,图片无法展示
|

网络异常,图片无法展示
|

4.8 多级嵌套

只需要在mapper接口中定义相关的类型转换方法即可,list类型也适用

4.8.1 方式1

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

4.8.2 方式2

通过uses配置类型转换

网络异常,图片无法展示
|

网络异常,图片无法展示
|

5.获取 mapper

5.1 通过 Mapper 工厂获取

我们都是通过 Mappers.getMapper(xxx.class) 的方式来进行对应 Mapper 的获取。此种方法为通过 Mapper 工厂获取。

如果是此种方法,约定俗成的是在接口内定义一个接口本身的实例 INSTANCE, 以方便获取对应的实例。

网络异常,图片无法展示
|

这样在调用的时候,我们就不需要在重复的去实例化对象了。类似下面

Target target = SourceMapper.INSTANCE.source2target(source);

5.2 使用依赖注入

对于 Web 开发,依赖注入应该很熟悉。MapSturct 也支持使用依赖注入,同时也推荐使用依赖注入。

网络异常,图片无法展示
|

@Mapper(componentModel = "spring")

5.3 依赖注入策略

可以选择是通过构造方法或者属性注入,默认是属性注入。

网络异常,图片无法展示
|

类似如此使用

@Mapper(componentModel = "cdi" injectionStrategy = InjectionStrategy.CONSTRUCTOR)

5.4 自定义类型转换

有时候,在对象转换的时候可能会出现这样一个问题,就是源对象中的类型是Boolean类型,而目标对象类型是String类型,这种情况可以通过@Mapper的uses属性来实现:

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

网络异常,图片无法展示
|

要注意的是,如果使用了例如像spring这样的环境,Mapper引入uses类实例的方式将是自动注入,那么这个类也应该纳入Spring容器

网络异常,图片无法展示
|

相关文章
|
30天前
|
缓存 安全 Java
你还在用 BeanUtils?试试 MapStruct,优雅的对象转换解决方案
你还在用 BeanUtils?试试 MapStruct,优雅的对象转换解决方案
27 0
|
2月前
|
安全 Java Maven
零配置,零麻烦:MapStruct 的轻松对象映射之旅
零配置,零麻烦:MapStruct 的轻松对象映射之旅
44 0
|
3月前
|
SQL Java 数据库连接
myabtis中为什么说 MyBatis 是半自动 ORM 映射工具?它与全自动的区别在哪里
myabtis中为什么说 MyBatis 是半自动 ORM 映射工具?它与全自动的区别在哪里
|
5月前
简化开发插件Lombok使用
简化开发插件Lombok,省去生成get、set、tostring、构造方法的时间,由插件生成。
27 0
|
8月前
|
Java 数据库连接 数据库
解析 Java 中的 @Mapper 注解:优雅实现对象映射的高效利器
在现代软件开发中,对象映射是一个常见的任务,而 Java 中的 `@Mapper` 注解则是实现对象映射的强大工具。通过该注解,我们可以轻松地定义对象之间的映射关系,提高代码的可读性和可维护性。本文将带您深入探索 Java 中的 `@Mapper` 注解,揭示其作用、用法以及在实际开发中的应用场景。
|
8月前
|
Java 数据库连接 数据库
探索Java中的MyBatis Plus:简化持久层开发的利器
在现代软件开发中,持久层是一个不可或缺的部分。为了更高效地操作数据库,开发者们经常使用ORM(对象关系映射)工具来简化数据库交互。而在Java领域,MyBatis Plus正是这样一个备受欢迎的ORM工具,它通过提供一系列便捷的特性,极大地简化了持久层的开发。本文将深入探讨MyBatis Plus的特点以及如何在项目中使用它。
83 0
|
10月前
|
SQL 存储 Java
如何模拟MyBatis对象映射赋值的过程,以及如何通过这种方式来简化我们的JDBC开发工作?
如何模拟MyBatis对象映射赋值的过程,以及如何通过这种方式来简化我们的JDBC开发工作?
72 0
|
10月前
|
Java 数据库连接 数据库
高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤(下)
高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤
75 1
|
10月前
|
Java 数据库连接 数据库
高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤(上)
高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤
109 1
|
Java 数据库连接 数据库
高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤
高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤
112 0
高效掌握JDBC技术(三)| 三层架构理念 | 书写符合事务特性的工具类 | JUnit测试框架 | JDBC项目开发步骤