MapStruct最详细的使用教程,别在用BeanUtils.copyProperties ()

1.各大培训机构,价格10万的视频 Java架构师视频免费送。

2.各种电子书籍经典Java书籍免费送

3.关注下方我的公众号进行免费获取。

4.个人技术总结免费赠送

 

1.为什么使用MapStruct

 

    在开发中你可曾遇到如下这样的问题?MyBtatis从数据库中查询的数据映射到domain的实体类上,然后有时候需要将domain的实体类映射给前端的VO类,用于展示。

    如下所示,假如Student是domain,而给前端展示的为StudentVO。

 

 

   有没有什么优雅的解决方式呢?可能你的第一反应就是使用Spring的BeanUtils.copyProperties (),但是BeanUtils.copyProperties ()只能转换类中字段名字一样且类型一样的字段。

   由于BeanUtils.copyProperties ()采用的是反射,实际上当重复调用时效率是比较低的。(实际测试实际测试Spring的BeanUtils在生成 次数为1000000时需要1.6秒,而使用MapStruct仅需要69毫秒)。

 

2.MapStruct的依赖

 

    首先导入Maven依赖

      ​​​​​

<dependency>
    <groupId>org.mapstruct</groupId>
    <!-- jdk8以下就使用mapstruct -->
    <artifactId>mapstruct-jdk8</artifactId>
    <version>1.2.0.Final</version>
 </dependency>
 
 <dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
     <version>1.2.0.Final</version>
 </dependency>

 

3.当成员变量名相同时的使用

 

    首先domain的Studnet类和StudentVO类如下,可以看到字段是完全一致的。其中@Data注解是lombok的表示含义如下,而@AllArgsConstructor则是提供所有参数的有参构造。

 

 

 

 

  写一个Mapper接口StudentMapper,此处的Mapper注解不是MyBtais的Mapper注解。

 

 

    接下来测试一下,看一下生成的结果。

 

 

 

4.成员变量名不相同时的使用

 

    Studnet类的age和name与StudentVO类的ageVO和nameVO对应不上时

 

 

 

    在Mapper类中加入@Mapping的注解指定原对象的字段名和要被对应上的字段名。其中@Mappings表示多个字段需要对应,如果只是一个可以使用@Mappin

 

 

 

    接下来测试一下,看一下生成的结果。

 

 

 

5.多参数源映射

 

    某些时候,我们的源不是一个,例如从数据库中查询出来了学生和老师,我们需要将老师的名字给VO的name字段,学生的年龄给VO的age字段时可以使用多参数源的映射方式。

 

 

 

    在Mapper类的toStudentVO可以看到带了两个参数,然后在@Mapping中使用形参的名字去点字段的名。

 

 

    接下来测试一下,看一下生成的结果。

 

 

 

6.多层嵌套映射

 

    有些时候我们需要多层映射,例如老师类中有自己的一个老婆类(男老师),然后我们需要将老师类中的老婆类的名字,赋值给VO,而年龄则使用学生的年龄。听上去怪怪的,就像学生有了老师的老婆😂 😂。

 

 

 

 

    同样可以在Mapper类中使用符号"."的方式进行映射。

 

 

    接下来测试一下,看一下生成的结果。

 

 

 

 

7.更新现有的Bean

 

    某些情况下,你需要不创建目标类型的新实例,而是更新该类型的现有实例的映射。可以通过为目标对象添加参数并使用@MappingTarget标记此参数来实现此类映射。

    例如Student我们将学生类的名字和年龄映射到VO中,但是不创建新的实例。

 

 

 

    在Mapper接口中使用@MappingTarget注解,被@MappingTarget注解标记的实例将从未被标记中进行的实例中进行映射。

 

 

    接下来测试一下,看一下生成的结果。

 

 

 

 

8.映射器工厂

 

    前面我们在Mapper接口中代码中一直有一行代码,如下所示,是MapStruct为我们提供的映射工厂,指定接口类型后自动帮我们创建接口的实现,且保证是线程安全的单例,无需自己手动创建。

 

 

 

9.依赖注入

 

    某些时候尤其是在做项目时,我们用到了Sping,希望映射后的新实例是交给Spring管理。这时候就需要进行依赖注入了。只需要在Mapper接口中的@Mapper注解中加入componentModel = "spring"即可。

 

 

 

10.数据类型转换

 

    映射属性在源对象和目标对象中具有相同的类型,这种情况不全有。例如,属性在源bean中可以是int类型,但在目标bean中可以是Long类型。另一个例子是对其他对象的引用,这些对象应该映射到目标模型中的相应类型。例如:Teachr类可能有一个Wife类型的属性wife,在映射VO对象时需要将其转换为StudentVO对象。

     在许多情况下,MapStruct会自动处理类型转换。例如,如果属性在源bean中的类型为int,但在目标bean中的类型为String,则生成的代码将分别通过调用String.valueOf(int)和Integer.parseInt(String)来透明地执行转换。

    通过案例来实现从int转换为String 从BigDecimal到String的转换 以及从Date到String的转换

 

 

 

 

    输出结果如下所示

 

 

 

 

11.映射集合

 

    在映射集合的时候,我们同样可以进行类型之间的转换,如下所示使用@MapMapping注解指定输出类型即可。

 

 

    输出结果如下所示

 

 

 

    当然MapStruct也支持其他各种类型的集合映射,上面只是举例了Map的映射

 

 

12.映射枚举

 

    MapStruct支持生成将一个Java枚举类型映射到另一个Java枚举类型的方法。默认情况下,源枚举中的每个常量都映射到目标枚举类型中具有相同名称的常量。如果需要,可以使用@ValueMapping注解将源枚举中的常量映射到具有其他名称的常量。源枚举中的几个常量可以映射到目标类型中的相同常量。

    Student中是SexEnum枚举,而StudentVO中是Sex2Enum,且枚举中的值是一致时,我们需要将Student中的映射到StudentVO中,此时只需要使用@Mapping来指定映射源和目标源的名称即可

 

 

 

 

 

    当枚举值一样时,直接使用@Mapping来指定映射源和目标源的名称即可

 

 

    当枚举值不一致时,使用@ValueMapping注解。

 

 

 

 

 

    使用@ValueMapping注解,同时由于Student和StudentVO中的枚举类型不一致,所以之前的@Mapping注解也要使用。

 

 

 

13.对象工厂

 

    有时候由于目标实例的构造方法被私有化后,我们使用原来的方式没办法进行,原因是MapStruct会在编译时去帮你实现,其中包含了调用构造方法。所以我们可以定义工厂的形式来生成实例,而让MapStruct去调用工厂来生成实例,而不再使用构造方法。

    有我们私有化了StudentVO的构造方法,如果直接使用MapStruct进行映射是会报错的。

 

 

    指定工厂,同时在Mapper接口中的@Mapper注解上加入工厂的class

 

 

 

    输出如下

 

 

 

 

14.自定义映射

 

    在某些情况下,可能需要定制生成的映射方法,在目标对象中设置一个无法由MapStruct生成的方法实现时,可以使用自定义映射来完成。假如我们的StudentVO中的age是无法生成的。

    首先定义类,然后实现Mapper接口,在重写的方法中写上需要的逻辑,且在Mapper接口中加入@DecorateWith注解,指定自定义映射的class。

 

 

 

    测试输出结果,可以看到先给age值为0,最后输出为100. 

 

 

 

    上面的MapStruct只写了一些常用的,以及我觉得可能会用到的,其中MapStruct还包含很多种用法,如果你想完全的了解他的所有功能,可以参考MapStruct的官方文档,文档地址可以在最下面可以看到。

文档地址:http://mapstruct.org/documentation/stable/reference/html/

  • 81
    点赞
  • 150
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值