Java实体对象转换利器MapStruct详解

概述

现在的JAVA项目多数采用分层结构,参考《阿里巴巴JAVA开发手册》。

分层之后,每一层都有自己的领域模型,即不同类型的 Bean:

DO Data Object :与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
DTO Data Transfer Object :数据传输对象, Service Manager 向外传输的对象。
BO Business Object :业务对象。由 Service 层输出的封装业务逻辑的对象。
AO Application Object :应用对象。在 Web 层与 Service 层之间抽象的复用对象模型,
极为贴近展示层,复用度不高。
VO View Object :显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
Query :数据查询对象,各层接收上层的查询请求。注意超过 2 个参数的查询封装,禁止
使用 Map 类来传输。
那么,进行就需要这些 对象的转换

例如将UserDo转换为UserVo就很普遍,如下所示:

public class UserDo{private String name;private Integer age;
}

转换为:

public class UserVo {private String name;private Integer age;
}

手动进行对象的转换,虽然执行性能很高,但是开发效率非常低下,且可能会存在错漏的情况。因此,我们会选择借助框架或是工具来实现对象的转换,之前常用BeanUtils(有多种可选,性能对比网上找找),现在多了一个选择就是MapStruct。

MapStruct

简介

MapStruct 是一个JSR 269 的 Java 注解处理器,是它是基于注解的,而且是编译时APT(annotation processor tool)。不像其他APT是运行时,例如Spring里面的注解处理方式,是在运行时通过反射的方式处理的。

使用

maven配置

    <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><mapstruct.version>1.5.3.Final</mapstruct.version><lombok.version>1.18.20</lombok.version><lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version></properties><dependencies><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${mapstruct.version}</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version><scope>provided</scope></dependency></dependencies><build><pluginManagement><plugins>...<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>${maven.compiler.source}</source><target>${maven.compiler.target}</target><annotationProcessorPaths><path><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>${mapstruct.version}</version></path><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></path><path><groupId>org.projectlombok</groupId><artifactId>lombok-mapstruct-binding</artifactId><version>${lombok-mapstruct-binding.version}</version></path></annotationProcessorPaths></configuration></plugin></plugins></pluginManagement></build>

应用

假设我们有如下两个需要转换的类:

@Data
public class UserDo {private String name;private String gender;private Double height;private Date birthday;private Address address;private String girlName;private String girlDes;
}@Data
public class UserVo {private String name;private String gender;private String height;private String bornDay;private AddressDto address;private GirlFriendDto girlFriend;
}

第一步: 定义一个interface,使用 @Mapper 标记。

第二步:构建一个实例属性用于访问里面的方法。

@Mapper
public interface UserConvetor {UserConvetor INSTANCE = Mappers.getMapper(UserConvetor.class);
}

 第三步:提供转换方法申明,必要时使用@Mapping注解

@Mapper
public interface UserConvetor {UserConvetor INSTANCE = Mappers.getMapper(UserConvetor.class);@Mapping(target = "bornDay", source = "birthday")UserVo toUserVo(UserDo userDo);
}

自定义映射

MapStruc默认会将两个bean的名称相同的属性进行映射,如果source与target的属性名称不一致则需要借助@Mapping注解。编译程序后就会在\target\generated-sources\annotations下产生UserConvetorImpl实现类了。

 第四步:代码中使用UserConvetor转换类

public void runConvetor(){UserDo userDo = new UserDo();userDo.setName("张三");...UserVo userVo= UserConvetor.INSTANCE.toUserVo(userDo);log.info("vo: {}", userVo);
}

忽略映射

如果不想给UserDobirthday赋值可以忽略它。

@Mapping(target = "bornDay", ignore = true)
UserVo toUserVo(UserDo userDo);

设置默认值

如果想实现在source值为null时给一个默认值也是可以了。

@Mapping(target = "gender", defaultValue = "man")
UserVo toUserVo(UserDo userDo);

设置常量

@Mapping(target = "height", constant = "175")

数据类型转换

日期类型转换

@Mapping(target = "bornDay", source = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
UserVo toUserVo(UserDo userDo);

小数点位数转换 

@Mapping(target = "height", source = "height" ,numberFormat = "#.00")

表达式 

大写转换

@Mapping(target = "name", expression = "java(programer.getName().toUpperCase())")

 方法调用

@Mapping(target = "name", expression = "java(nameToUp(userDo))")
UserVo toUserVo(UserDo userDo);default String nameToUp(UserDo userDo){return Optional.ofNullable(userDo).filter(Objects::nonNull).map(u->u.getName()).orElse(null).toUpperCase();
}

 

嵌套映射

我们经常会遇到bean里面套着bean的映射。

{"name":"shusheng007","address":{"country":"China","city":"TianJin"}
}

对于这样的映射,我们只需要在mapper中提供一个嵌套bean的转换关系即可。

@Mapping(target = "address", source = "address")
UserVo toUserVo(UserDo userDo);
//嵌套bean的转换关系
AddressDto toAddressDto(Address addr);

集合映射

只需要提供集合元素类型的映射即可。

AddressDto toAddressDto(Address addr);List<AddressDto> toAddressList(List<Address> addrList);

多个数据对象

@Mapping(target = "name", source = "programer.name")
@Mapping(target = "girlFriendName", source = "girl.name")
UserVo toUserVo(UserDo userDo, Gir girl);

 其他还有外部引用、切面操作在此就不一一列举。

IDE 插件

MapStruct 提供了 IDEA MapStruct Support 插件,让我们在 IDEA 中,可以更愉快的使用 MapStruct!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1556625.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

游戏盾是如何解决游戏行业攻击问题

随着游戏行业的迅猛发展&#xff0c;其高额的利润和激烈的市场竞争吸引了众多企业和创业者的目光。然而&#xff0c;这一行业也面临着前所未有的业务和安全挑战&#xff0c;尤其是DDoS&#xff08;分布式拒绝服务&#xff09;攻击&#xff0c;已经成为游戏行业的一大威胁。今天…

C语言基础(10)之指针(2)

在上一篇文章中我们谈到了指针&#xff0c;并给老铁们讲解了什么是指针、指针类型、野指针以及指针运算等知识。在这篇文章中小编将继续带大家了解指针的相关知识点。 1. 指针和数组 指针和数组之间又能有什么联系呢&#xff1f;在谈这个之前&#xff0c;我们先来讲讲指针和数…

Android15车载音频之Virtualbox中QACT实时调试(八十八)

简介: CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布:《Android系统多媒体进阶实战》🚀 优质专栏: Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏: 多媒体系统工程师系列【原创干货持续更新中……】🚀 优质视频课程:AAOS车载系统+…

微信小程序开发-调试及配置文件介绍

一&#xff0c;隐藏控制台系统日志 在小程序开发中&#xff0c;如果你想要隐藏控制台中的系统日志&#xff0c;可以通过以下步骤进行操作&#xff1a; 打开小程序的开发工具。在开发工具的控制台(Console)中&#xff0c;找到你想要隐藏的系统日志。右键点击该系统日志条目。在…

MySQL连接查询:外连接

先看我的表结构 dept表 emp表 外连接分为 1.左外连接 2.右外连接 1.左外连接 基本语法 select 字段列表 FORM 表1 LEFT [OUTER] JOIN 表2 ON 条件;例子&#xff1a;查询emp表的所有数据&#xff0c;和对应部门的员工信息&#xff08;左外连接&#xff09; select e.*, d.n…

利士策分享,旅游是否要舟车劳顿才能尽兴?

利士策分享&#xff0c;旅游是否要舟车劳顿才能尽兴&#xff1f; 国庆假期&#xff0c;当夜幕降临&#xff0c;城市灯火阑珊&#xff0c;一场关于美食与等待的较量悄然上演。 李女士在北京天坛公园附近餐厅的等位经历——前方1053桌的壮观景象&#xff0c;不仅让人咋舌&#xf…

信息学奥赛复赛复习14-CSP-J2021-03网络连接-字符串处理、数据类型溢出、数据结构Map、find函数、substr函数

PDF文档回复:20241007 1 P7911 [CSP-J 2021] 网络连接 [题目描述] TCP/IP 协议是网络通信领域的一项重要协议。今天你的任务&#xff0c;就是尝试利用这个协议&#xff0c;还原一个简化后的网络连接场景。 在本问题中&#xff0c;计算机分为两大类&#xff1a;服务机&#x…

3. BBP系列运动控制板(飞控板)简介

3.1. 概述 Bread Board Pilot(简称BBP) 是在积累了前期 Single Pilot 及 PH7 飞控板大量设计及使用经验的基础上&#xff0c;全新基于PH47代码框架开发的高灵活性&#xff0c; 高性能&#xff0c; 超低成本的最新一代飞控板设计。 目前&#xff0c;因为其使用便捷灵活&#xf…

Hallo部署指南

一、介绍 Hallo是由复旦大学、百度公司、苏黎世联邦理工学院和南京大学的研究人员共同提出的一个AI对口型肖像图像动画技术&#xff0c;可基于语音音频输入来驱动生成逼真且动态的肖像图像视频。 该框架采用了基于扩散的生成模型和分层音频驱动视觉合成模块&#xff0c;提高了…

【AI知识点】正则化(Regularization)

正则化&#xff08;Regularization&#xff09; 是机器学习和统计学中的一种技术&#xff0c;用于防止模型过拟合。在训练模型时&#xff0c;模型可能会过度拟合训练数据&#xff0c;导致在新数据上的表现较差。正则化通过在优化过程中引入额外的约束或惩罚项&#xff0c;使模型…

【开发心得】筑梦上海:项目风云录(6)

目录 会海跳槽 票务开启 漂泊在外的日子 未完待续 会海跳槽 随着时刻表的出炉&#xff0c;意味着大规模的界面开发逐步进入正规。项目组里陆陆续续引进了8个人&#xff0c;最多的时候&#xff0c;同时有10个人在现场。“松工”为我们准备的办公室坐的满满当当&#xff0c;…

Maven 高级之分模块设计与继承、聚合

在软件开发中&#xff0c;随着项目规模的扩大&#xff0c;代码量和复杂度不断增加&#xff0c;传统的一体化开发模式逐渐暴露出诸多问题。为了解决这些问题&#xff0c;模块化开发应运而生&#xff0c;而 Maven 正是模块化开发的利器&#xff0c;它提供的继承和聚合机制为构建和…

wc命令:统计文本行数、单词数、字节数

一、命令简介 ​wc​&#xff08;word count&#xff09;是一个在类 Unix 系统中常用的命令行工具&#xff0c;用于统计文本文件的 行数​、单词数 ​和 字节数​。 ​​ ‍ 二、命令参数 ​wc​ 命令的基本语法如下&#xff1a; wc [选项] 文件选项&#xff1a; ​-c​…

当管理遇上AI,工作效率翻了3倍!

最近这段时间&#xff0c;很多企业都开始降薪、裁员。 在降本增效的大背景下&#xff0c;企业但凡有什么大动作&#xff0c;压力往往都会转嫁到管理者的身上。 一方面&#xff0c;要调大家的状态&#xff0c;处理团队中的各种琐事&#xff1b;另一方面&#xff0c;要及时响应…

【ESP32】Arduino开发 | Timer定时器+定时器闹钟例程

有关定时器外设的详细介绍在ESP-IDF的对应文章中&#xff0c;跳转栏目目录可以找到。 1. API 1.1 启动定时器 hw_timer_t * timerBegin(uint8_t timer, uint16_t divider, bool countUp); timer&#xff1a;定时器序号&#xff08;ESP32有4个硬件定时器&#xff0c;所以可填序…

SpringBoot赋能旅游管理:系统设计与实现

第三章 系统分析 3.1可行性分析 对所有的系统来说&#xff0c;都有可能会受到时间和空间上的制约。所以&#xff0c;我们在设计每一个项目的时候&#xff0c;必须对该系统实行可行性分析&#xff0c;这样不但能够降低项目的危害&#xff0c;还能改降低人力、物力和财力的损耗。…

【CKA】十六、监控Pod度量指标

16、监控Pod度量指标 1. 考题内容&#xff1a; 2. 答题思路&#xff1a; 题目意思是&#xff1a;找出label有namecpu-user的CPU最高的Pod&#xff0c;然后把它的名字写在已经存在的 /opt/KUTR00401/KUTR00401.txt文件里 3. 官网地址&#xff1a; https://kubernetes.io/zh-…

LeetCode 54 Spiral Matrix 解题思路和python代码

题目&#xff1a; Given an m x n matrix, return all elements of the matrix in spiral order. Example 1: Input: matrix [[1,2,3],[4,5,6],[7,8,9]] Output: [1,2,3,6,9,8,7,4,5] Example 2: Input: matrix [[1,2,3,4],[5,6,7,8],[9,10,11,12]] Output: [1,2,3,4,8,1…

反射在Go语言中的具体应用场景

在Go语言中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的特性&#xff0c;它允许程序在运行时检查、修改和操作变量的类型信息。 尽管反射在性能上通常不如直接操作&#xff0c;但它在某些特定场景下非常有用。 反射在Go语言中的具体应用场景&#xff1a;…

基于JAVA的鲜花商城管理系统(源码+定制+讲解)鲜花商城管理系统、鲜花商城管理平台、鲜花商城信息管理、鲜花商城系统开发与应用、鲜花在线商城管理系统

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…