Java MapStruct 字段映射工具类

2024-05-03 11:04
文章标签 java 工具 映射 mapstruct

本文主要是介绍Java MapStruct 字段映射工具类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

      • MapStruct 字段映射工具类
        • 1、MapStruct官网
        • 2、MapStruct的使用场景
        • 3、MapStruct的使用
          • A.需要进行转换的实体类
          • B.引入依赖
          • C.定义一个做映射的接口
          • D.测试代码
        • 4、MapStruct处理字段映射
          • A.名字不一致时的映射
          • B.可以自动映射的类型
          • C.自定义常量
          • D. 类型不匹配时的映射
        • 5、MapStruct的性能

MapStruct 字段映射工具类

1、MapStruct官网

MapStruct官网
MapStruct官网示例
Mapstruct是一种代码生成器,它极大地简化了基于"约定优于配置"方法的Java bean类型之间映射
的实现。生成的映射代码使用纯方法调用,因此快速、类型安全且易于理解。

约定优于配置,也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做决定的数
量,获得简单的好处,而又不失灵活性。
2、MapStruct的使用场景

主要用于处理不同业务分层中产生的实体类如在数据存储层,使用DO来抽象一个业务实体;在业务
逻辑层,使用DTO来表示数据传输对象;到了展示层,又把对象封装成VO来与前端进行交互。字段
相差不大而定义了多重类。通过使用get/set方法进行取值赋值。

personDTO.setName(personDO.getName());
personDTO.setAge(personDO.getAge());
personDTO.setSex(personDO.getSex());
personDTO.setBirthday(personDO.getBirthday());
3、MapStruct的使用
A.需要进行转换的实体类
public class PersonDO {private Integer id;private String name;private int age;private Date birthday;private String gender;}public class PersonDTO {private String userName;private Integer age;private Date birthday;private Gender gender;
}
B.引入依赖
...
<properties><org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
</properties>
...<dependencies><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${org.mapstruct.version}</version></dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${org.mapstruct.version}</version><scope>provided</scope></dependency>
</dependencies>

因为MapStruct需要在编译器生成转换代码,所以需要在maven-compiler-plugin插件中配置上对
mapstruct-processor的引用。

C.定义一个做映射的接口

使用注解@Mapper定义一个Converter接口,在其中定义一个do2dto方法,方法的入参类型是
PersonDO,出参类型是PersonDTO,这个方法就用于将PersonDO转成PersonDTO。

@Mapper
interface PersonConverter {PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);@Mappings(@Mapping(source = "name", target = "userName"))PersonDTO do2dto(PersonDO person);
}
D.测试代码
public static void main(String[] args) {PersonDO personDO = new PersonDO();personDO.setName("Fcant");personDO.setAge(18);personDO.setBirthday(new Date());personDO.setId(1);personDO.setGender(Gender.MALE.name());PersonDTO personDTO = PersonConverter.INSTANCE.do2dto(personDO);System.out.println(personDTO);
}

输出结果:

PersonDTO{userName='Fcant', age=18, birthday=Sat Aug 08 19:00:44 CST 2020, gender=MALE}
4、MapStruct处理字段映射

要转换的两个类中源对象属性与目标对象属性的类型和名字一致的时候,会自动映射对应属性。

A.名字不一致时的映射

在PersonDO中用name表示用户名称,而在PersonDTO中使用userName表示用户名。
这时候就要使用@Mapping注解了,只需要在方法签名上,使用该注解,并指明需要转换的源对象
的名字和目标对象的名字就可以了,如将name的值映射给userName,可以使用如下方式:

@Mapping(source = "name", target = "userName")
B.可以自动映射的类型

MapStruct会对部分类型自动做映射,不需要做额外配置。
一般情况下,对于以下情况可以做自动类型转换:

  • 基本类型及其包装类型。

  • 基本类型的包装类型和String类型之间

  • String类型和枚举类型之间

C.自定义常量

在转换映射过程中,给一些属性定义一个固定的值,这个时候可以使用 constant

@Mapping(source = "name", constant = "Fcant")
D. 类型不匹配时的映射
public class PersonDO {private String name;private String address;
}
public class PersonDTO {private String userName;private HomeAddress address;
}
@Mapper
interface PersonConverter {PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);@Mapping(source = "userName", target = "name")@Mapping(target = "address",expression = "java(homeAddressToString(dto2do.getAddress()))")PersonDO dto2do(PersonDTO dto2do);default String homeAddressToString(HomeAddress address){return JSON.toJSONString(address);}
}

只需要在PersonConverter中在定义一个方法(因为PersonConverter是一个接口,所以在JDK 1.8以后的版本中可以定义一个default方法),这个方法的作用就是将HomeAddress转换成String类型。

default方法:Java 8 引入的新的语言特性,用关键字default来标注,被default所标注的方法,需要提供实现,而子类可以选择实现或者不实现该方法

然后在dto2do方法上,通过以下注解方式即可实现类型的转换:

@Mapping(target = "address",expression = "java(homeAddressToString(dto2do.getAddress()))")

上面这种是自定义的类型转换,还有一些类型的转换是MapStruct本身就支持的,如String和Date之间的转换:

@Mapping(target = "birthday",dateFormat = "yyyy-MM-dd HH:mm:ss")@Mapping(target = "birthday",dateFormat = "yyyy-MM-dd HH:mm:ss")
5、MapStruct的性能

MapStruct在编译时生成bean映射,这确保了高性能,可以提前将问题反馈出来,也使得开发人员可以彻底的错误检查。
在代码中使用了很多MapStruct提供的注解,这使得在编译期,MapStruct就可以直接生成bean映射的代码,相当于MapStruct写了很多setter和getter。
如在代码中定义了以下一个Mapper

@Mapper
interface PersonConverter {PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);@Mapping(source = "userName", target = "name")@Mapping(target = "address",expression = "java(homeAddressToString(dto2do.getAddress()))")@Mapping(target = "birthday",dateFormat = "yyyy-MM-dd HH:mm:ss")PersonDO dto2do(PersonDTO dto2do);default String homeAddressToString(HomeAddress address){return JSON.toJSONString(address);}
}

经过代码编译后,会自动生成一个PersonConverterImpl:

@Generated(value = "org.mapstruct.ap.MappingProcessor",date = "2020-08-09T12:58:41+0800",comments = "version: 1.3.1.Final, compiler: javac, environment: Java 1.8.0_181 (Oracle Corporation)"
)class PersonConverterImpl implements PersonConverter {@Overridepublic PersonDO dto2do(PersonDTO dto2do) {if ( dto2do == null ) {return null;}PersonDO personDO = new PersonDO();personDO.setName( dto2do.getUserName() );if ( dto2do.getAge() != null ) {personDO.setAge( dto2do.getAge() );}if ( dto2do.getGender() != null ) {personDO.setGender( dto2do.getGender().name() );}personDO.setAddress( homeAddressToString(dto2do.getAddress()) );return personDO;}
}

在运行期,对于bean进行映射的时候,就会直接调用PersonConverterImpl的dto2do方法,这样就没有什么特殊的事情要做了,只是在内存中进行set和get就可以了。因为在编译期做了很多事情,所以MapStruct在运行期的性能会很好,并且还有一个好处,那就是可以把问题的暴露提前到编译期。使得如果代码中字段映射有问题,那么应用就会无法编译,强制开发者要解决这个问题才行。

这篇关于Java MapStruct 字段映射工具类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/956598

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Java中的.close()举例详解

《Java中的.close()举例详解》.close()方法只适用于通过window.open()打开的弹出窗口,对于浏览器的主窗口,如果没有得到用户允许是不能关闭的,:本文主要介绍Java中的.... 目录当你遇到以下三种情况时,一定要记得使用 .close():用法作用举例如何判断代码中的 input

基于Python开发Windows自动更新控制工具

《基于Python开发Windows自动更新控制工具》在当今数字化时代,操作系统更新已成为计算机维护的重要组成部分,本文介绍一款基于Python和PyQt5的Windows自动更新控制工具,有需要的可... 目录设计原理与技术实现系统架构概述数学建模工具界面完整代码实现技术深度分析多层级控制理论服务层控制注