MapStruct 超神进阶用法,让你的代码效率提升十倍!

前言

MapStruct 是一个 Java 编译时注解处理框架,用来自动化将一种 Java Bean 对象映射成另一种类型的对象。

该框架的主要目标是使开发人员在尽可能少的代码和最低的运行时间成本下实现属性映射。MapStruct 通过在编译时生成代码来实现这点,这与大多数其他 Java Bean 映射框架在运行时通过反射进行映射形成了鲜明对比。

MapStruct 具有以下主要特性:

  • 简洁: 简化了 Java Beans 之间转换的代码,自动生成使用简单的赋值语句完成的映射实现。
  • 性能优秀: 由于 MapStruct 是在编译时生成代码,不涉及任何反射,因此执行映射的性能优越。
  • 安全: 通过在编译时生成映射代码,MapStruct 提供了类型安全的映射,并能在编译时就发现潜在的错误。
  • 灵活: 可通过自定义转换方法、类型转换和映射策略等来满足复杂的映射需求。
  • 良好的 IDE 支持: 由于 MapStruct 是编译时工具,所以拥有良好的 IDE 集成,如代码自动完成、错误高亮等。

总的来说, MapStruct 是一个强大且灵活的映射框架,很好的解决有关对象转换的问题,实现了代码的简洁和性能的兼顾。MapStruct的常规用法,网上有很多教程了,本文将列举一些进阶用法,方便日常开发使用。

expression​

在转化的时候,执行 java 表达式,直接看例子:

@Mapper(componentModel = "spring")
public interface MyMapper {@Mapping(target = "createTime", expression = "java(System.currentTimeMillis())")Target toTarget(Source source);
}

转化成 target 对象时,createTime字段的值,会设置为​​System.currentTimeMillis()​​,生成的代码如下:

@Component
public class MyMapperImpl implements MyMapper {@Overridepublic Target toTarget(Source source) {Target target = new Target();target.setCreateTime( System.currentTimeMillis() );return target;}
}

qualifiedByName​

做映射时,默认情况下,从source 字段到target 字段是直接使用 ​​get/set​​,如下:

@Data
public class Source {private String name;
}@Data
public class Target {private String name;
}@Mapper(componentModel = "spring")
public interface MyMapper {Target toTarget(Source source);
}

生成的转化代码类如下:

@Component
public class MyMapperImpl implements MyMapper {@Overridepublic Target toTarget(Source source) {if ( source == null ) {return null;}Target target = new Target();// 无脑 set/gettarget.setName( source.getName() );return target;}
}

如果这种直接的 ​​set/get​​ 无法满足需求,比如需要把 name 转化成大写格式,那么可以使用​​qualifiedByName​​:

@Mapper(componentModel = "spring")
public interface MyMapper {@Mapping(target = "name", source = "name", qualifiedByName = "toUpperCase")Target toTarget(Source source);@Named("toUpperCase")default String toUpperCase(String value) {// 这里写转换大写的逻辑return value == null ? null : value.toUpperCase();}
}

生成的代码如下:

@Component
public class MyMapperImpl implements MyMapper {@Overridepublic Target toTarget(Source source) {if ( source == null ) {return null;}Target target = new Target();target.setName( toUpperCase( source.getName() ) );return target;}
}

nullValueMappingStrategy​

如果 source 为 null 时,对应的 target 的处理策略,默认是 ​​NullValueMappingStrategy.RETURN_NULL​​,即 target 中对应的字段也设置为 null。

但有时候设置为 null 可能不符合我们的需求,比如 target 中有个 List ids,我们希望如果 source 中ids 为 null 时,target 的 ids 设置为空 list。这时候可以使用​​nullValueMappingStrategy​​策略中的​​NullValueMappingStrategy.RETURN_DEFAULT​​。

​nullValueMappingStrategy​​ 可以使用在某个方法上(只对该方法生效),也可以使用在类上(对类中的所有方法都生效),如下:

@Component
public class MyMapperImpl implements MyMapper {@Overridepublic Target toTarget(Source source) {if ( source == null ) {return null;}Target target = new Target();target.setName( source.getName() );List<Integer> list = source.getIds();if ( list != null ) {target.setIds( new ArrayList<Integer>( list ) );}else {target.setIds( null );}return target;}
}

指定​​NullValueMappingStrategy.RETURN_DEFAULT​​策略后:

@Mapper(componentModel = "spring",nullValueMappingStrategy = org.mapstruct.NullValueMappingStrategy.RETURN_DEFAULT)
public interface MyMapper {Target toTarget(Source source);
}@Component
public class MyMapperImpl implements MyMapper {@Overridepublic Target toTarget(Source source) {Target target = new Target();if ( source != null ) {target.setName( toUpperCase( source.getName() ) );List<Integer> list = source.getIds();if ( list != null ) {target.setIds( new ArrayList<Integer>( list ) );}else {target.setIds( new ArrayList<Integer>() );}}return target;}
}

可以看到,当 source 或者 ​​source.ids​​ 为 null 时,返回的 target 和 ​​target.ids​​ 都是默认的空值(空对象+空 list)。

Decorator​

你可以通过创建一个 ​​Decorator​​ 类来对你的方法进行修饰并实现全局处理。

以下是一个例子:

public abstract class YourMapperDecorator implements YourMapper {private final YourMapper delegate;public YourMapperDecorator(YourMapper delegate) {this.delegate = delegate;}@Overridepublic Target toTarget(Source source) {Target result = delegate.toTarget(source);if (result != null) {if (result.getField() == null) {result.setField("");}// 你可以在这里对其他字段进行同样的处理...}return result;}
}

然后你只需在你的 Mapper 接口上添加 ​​@DecoratedWith​​ 注解:

@Mapper
@DecoratedWith(YourMapperDecorator.class)
public interface YourMapper {Target toTarget(Source source);
}

这样,每次调用 ​​toTarget​​ 方法时,​​YourMapperDecorator​​ 中的实现会被调用。在这里,你可以实现任何你想要的逻辑,例如对空字段赋予特定的默认值。

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

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

相关文章

POST请求的艺术:如何有效使用POST方法

在HTTP协议中&#xff0c;POST方法是一种用于向服务器提交数据的请求方式。与GET请求不同&#xff0c;POST请求将数据包含在请求体&#xff08;request body&#xff09;中&#xff0c;而不是URL中。这使得POST请求更适合传输大量数据和敏感信息。本文将探讨如何有效使用POST方…

【递归】4.二叉树的前序遍历

1 题目解析 题目链接&#xff1a;二叉树的前序遍历 题目描述如下&#xff1a; 先回顾一下&#xff0c;二叉树的前序遍历的过程是&#xff1a;先遍历根&#xff0c;再遍历左子树&#xff0c;最后遍历右子树。 所以顺序就是&#xff1a;根&#xff0c;左子树&#xff0c;右子树…

Supabase 入门指南

Supabase 是一个开源替代品&#xff0c;用于 Firebase 提供的后端服务。它基于 PostgreSQL&#xff0c;提供实时数据库、身份验证、存储等功能。本文将深入探讨 Supabase 的主要功能&#xff0c;并结合不同场景给出代码实例。 1. 创建 Supabase 项目 首先&#xff0c;访问 S…

vulnhub靶场Matrix-win全流程

Matrix-Breakout 2 Morpheus&#xff08;win操作&#xff09; 如果靶场出现发送数据包无响应的情况&#xff0c;请重启服务器 靶机下载地址&#xff1a; https://download.vulnhub.com/matrix-breakout/c-2-morpheus.ova攻击机&#xff1a;win11(192.168.5.1) 信息收集 本…

React学习笔记(四)——React 组件生命周期

目录 1. 生命周期-概览 2. 生命周期-挂载阶段 3. 生命周期-更新阶段 4. 生命周期-卸载阶段 5. setState扩展-发现问题 6. setState扩展-更多用法 7. setState扩展-异步 1. 生命周期-概览 了解react类组件生命周期整体情况 大致步骤&#xff1a; 什么是生命周期React类组…

C盘空间不足--WizTree(管理空间)

WizTree&#xff1a;高效的磁盘空间分析工具 在日常使用电脑的过程中&#xff0c;磁盘空间的管理常常成为一个棘手的问题。随着文件的不断增加&#xff0c;我们的硬盘空间逐渐被占满&#xff0c;而这些文件中有很多其实并不重要。为了帮助用户更好地管理磁盘空间&#xff0c;Wi…

已存在的Python项目使用依赖管理工具UV

1. 文档 uv文档 2. 如何转换 初始化 uv initrequirements.txt转换成pyproject.toml uv add $(cat requirements.txt)删除requirements.txt 如果更新pyproject.toml之后&#xff0c;使用命令 uv sync替换项目环境 如果有库没有加入依赖&#xff0c;自己手动加一下&am…

美化网页,特效

当阅读博客园的文章时&#xff0c;经常看到精美的特效 博客园美化 - 凌云 - 博客园 (cnblogs.com) 简直不要太好看 自己写了一个前后端分离的网站后&#xff0c;想着应用这些特效&#xff0c;毕竟别人看到特效后逼格还是挺高的 于是&#xff0c;我F12把代码拿了下来 【手动狗…

普通人想自学AI产品经理,我劝你谨慎!

随着大模型技术的快速发展&#xff0c;市面上涌现出了大量的大模型产品岗位&#xff0c;那么想要进入AI行业的产品经理同学&#xff0c;需要提前做好哪些准备工作呢&#xff1f;这篇文章里&#xff0c;作者总结了入行AI的必备知识&#xff0c;包括市场调研、产品底层逻辑等内容…

逆概率加权(R和Python案例)

逆概率加权&#xff08;Inverse Probability Weighting, IPW&#xff09;是一种统计技术&#xff0c;用于观察性研究中调整混杂变量的影响&#xff0c;以便更准确地估计因果关系。这种方法特别有用于在无法进行随机化实验的情况下&#xff0c;通过给予不同个体不同的权重&#…

2024年9月最新web3开发人员薪资情况(包括不同语言、各个国家)

2024年9月最新web3非开发人员薪资情况&#xff08;包括不同语言、各个国家&#xff09; 开发人员的薪水是多少&#xff1f; Web3 开发人员的平均年薪为 14 万至 20 万美元。 量化开发人员每年可赚 20 万至 30 万美元 高级开发人员年薪 16 万至 25.7 万美元 北美开发商年薪 …

了解云计算工作负载保护的重要性,确保数据和应用程序安全

云计算de小白 云计算技术的快速发展使数据和应用程序安全成为一种关键需求&#xff0c;而不仅仅是一种偏好。随着越来越多的客户公司将业务迁移到云端&#xff0c;保护他们的云工作负载&#xff08;指所有部署的应用程序和服务&#xff09;变得越来越重要。云工作负载保护&…

可视掏耳勺鸡肋吗?高清可视掏耳勺牌子推荐!

很多人习惯在洗漱完顺手拿一根棉签掏耳朵&#xff0c;但是棉签的表面直径大且粗糙&#xff0c;不易将耳朵深处的耳垢挖出&#xff0c;耳垢堆积在耳道深处长时间不清理会导致堵塞耳道&#xff0c;引起耳鸣甚至感染。而可视掏耳勺作为一种新型的挖耳工具&#xff0c;它的安全性也…

【java常见面试题】

IO 按照流的流向分类&#xff1a;输入流和输出流 按照操作单元分类&#xff1a;可以分为字节流和字符流 按照流的角色划分&#xff1a;节点流和处理流 所有输入流的基类&#xff1a;InputStream/Reader 字节流/字符流 所有输出流的基类&#xff1a;OutputStream/Reader 字…

用友或畅捷通设置外网访问,使用的是神卓互联内网穿透

本文将详细介绍如何使用神卓互联内网穿透技术搭建单位用友软件的访问环境&#xff0c;以实现远程办公和管理的高效便捷。 目录 一、神卓互联内网穿透技术 二、准备工作 1. 注册神卓互联账号 2. 配置用友软件服务器 三、配置神卓互联内网穿透 1. 安装并启动神卓互联客户端…

吉客云与金蝶云星空对接集成分页查询货品信息连通[标准]

吉客云与金蝶云星空对接集成分页查询货品信息连通[标准][付款单新增]-v1(付款单) 对接系统&#xff1a;吉客云 “吉客云”是一站式企业数字化解决方案系统&#xff0c;可实现业务、财务、办公、人事等一体化管理。相对于传统多套软件系统的集成方案&#xff0c;“吉客云”具有业…

【程序员提效】AI助力程序员提效:如何让AI编写代码+调试复杂代码教程

在编程的旅途中&#xff0c;程序员们常常面临各种挑战&#xff0c;尤其是在编写和维护代码时&#xff0c;难题层出不穷。&#x1f914; 尽管传统搜索引擎提供了海量信息&#xff0c;但往往让我们在无尽的例子和复杂分析中迷失&#xff0c;难以找到真正适合自己的解决方案。正因…

韦唯出席平遥国际电影展开幕式 中英文歌曲连唱尽显国际范

9月24日&#xff0c;第八届平遥国际电影展在在山西省晋中市平遥古城正式开幕。韦唯作为特邀演出嘉宾&#xff0c;参加开幕式晚会并演唱《黄土地》主题曲《女儿歌》及自己的英文单曲《All there is》两首歌曲。 韦唯刚结束“湾区升明月”2024大湾区电影音乐晚会&#xff0c;就马…

Cloudera 安装不再难:下载安装全流程指南

引言&#xff1a;之前文章《深度挖掘&#xff5c;Cloudera安装不再难&#xff01;基础环境搭建全解析》中&#xff0c;我们深入探讨了如何在企业环境中精心准备系统环境&#xff0c;为大数据平台Cloudera 搭建奠定坚实基础。今天&#xff0c;我们将正式进行Cloudera Manager的下…

出国留学:如何选对专业,匹配你的职业目标?

在全球化日益加深的今天&#xff0c;出国留学已成为许多青年学子拓宽视野、提升竞争力的重要途径。然而&#xff0c;面对琳琅满目的专业选择&#xff0c;如何找到既符合个人兴趣又能助力未来职业发展的专业&#xff0c;成为了每位准留学生必须面对的挑战。本文将为您详细解析&a…