比较 Java 中的 ModelMapper 和 MapStruct:自动映射器的强大功能

news/2024/11/17 6:48:31/

        了解如何在自动映射器 ModelMapper 和 MapStruct 之间进行选择,以提高生产力和可维护性,并减少数据映射中的错误。

        在 Java 应用程序中, 数据映射 是一项常见任务,涉及将对象从一种类型转换为另一种类型。这个过程可能会变得复杂而乏味,特别是在处理大型嵌套类时。为了简化此任务,开发人员经常求助于自动映射框架。Java 中自动映射的两个流行选择是 ModelMapper 和 MapStruct。在本文中,我们将比较这些框架,并探讨为什么使用自动映射器比手动映射更有好处。

对自动制图器的需求

在深入比较之前,让我们先了解为什么自动映射器比手动映射更受青睐。以下是一些关键原因:

  1. 生产力:手动映射需要编写样板代码来在类之间传输数据。它可能非常耗时且容易出错,尤其是在具有许多类的应用程序中。自动映射器为您生成映射代码,节省宝贵的开发时间。
  2. 可维护性:随着应用程序的发展,类可能会发生变化,导致映射逻辑频繁更新。自动映射器会自动处理这些更改,从而降低更新期间引入错误的风险。
  3. 减少人为错误:手动映射涉及编写重复代码,这增加了人为错误的可能性。自动映射器确保类之间的映射一致且准确。
  4. 可读性:自动映射器提供了更干净、更简洁的映射代码,使开发人员更容易理解数据流。
  5. 灵活性:自动映射器通常允许自定义和配置来处理复杂的映射场景。

ModelMapper 与 MapStruct

ModelMapper 和 MapStruct 是 Java 生态系统中强大且广泛使用的映射框架。让我们根据各种因素对它们进行比较:

  1. 易于使用:ModelMapper 以其简单性和易用性而闻名。它自动映射具有相同名称和数据类型的字段。另一方面,MapStruct 要求开发人员编写显式映射接口,这可能导致更多的初始设置,但提供了对映射过程的更多控制。
  2. 性能:由于其编译时代码生成方法,MapStruct 的性能优于 ModelMapper。ModelMapper 依赖于反射,这可能会产生轻微的性能开销。
  3. 配置:ModelMapper提供了丰富的配置选项,支持复杂的映射场景。MapStruct 作为编译时映射器,需要显式映射接口,这既可以是优点(静态类型),也可以是缺点(更多初始设置)。
  4. 定制:两个框架都允许定制转换器来处理特定的映射情况。然而,ModelMapper 提供了更多的内置转换,并且在许多场景中需要更少的自定义转换器。

ModelMapper 和 MapStruct 都是 Java 中自动映射的绝佳选择,决定使用其中一种主要取决于项目的具体要求和偏好。

超越 DTO:自动映射器的各种用例

除了简单的DTO映射之外,自动映射器还可以通过多种方式使用。让我们探讨一些其他用例:

  1. 层之间的转换:自动映射器可以将域对象转换为 DTO、表示模型或应用程序层之间的任何其他数据转换。
  2. 遗留代码中的适配器和转换:在处理遗留代码库时,自动映射器可以充当适配器来弥合新旧类结构之间的差距。它们使得引入现代数据模型变得更容易,同时仍然支持现有的代码库。
  3. API版本控制:随着应用程序的发展并引入新的API版本,自动映射器可以在不同版本之间转换数据模型,确保向后兼容性和平滑迁移。

        该表比较了 Java 生态系统中著名的自动映射框架:ModelMapper 和 MapStruct。这些框架提供了在不同类型之间转换对象的有效解决方案,消除了手动映射的需要并提高了开发人员的工作效率。

        ModelMapper 以其用户友好的方法脱颖而出,需要最少的设置和配置。其简单的用法使开发人员能够快速开始数据映射任务。该框架丰富的配置选项提供了极大的灵活性,使其能够轻松处理复杂的映射场景。此外,ModelMapper支持自定义转换器,可以方便地满足特定的映射要求。

        另一方面,MapStruct 遵循编译时代码生成方法,因此与 ModelMapper 相比具有卓越的性能。它需要显式映射接口的定义,这可能需要更多的设置工作。然而,这种方法可以更好地控制映射过程,为开发人员提供细粒度的定制。

        ModelMapper 和 MapStruct 与Spring 和CDI等流行的 Java 框架无缝集成,允许开发人员通过依赖注入支持将自动映射合并到他们的项目中。这种无缝集成使开发人员能够充分利用这些框架的功能,同时受益于 ModelMapper 或 MapStruct 强大的映射功能。

        ModelMapper 和 MapStruct 之间的选择取决于项目要求和偏好。ModelMapper 以其简单性和功能丰富的配置而著称,而 MapStruct 则具有出色的性能并提供对映射的更多控制。开发人员可以根据自己的具体需求自信地选择最合适的框架,增强整体开发体验并简化 Java 应用程序中的数据映射任务。

 

实践会话:将交付映射到DeliveryDTO

让我们深入实践一下,我们将使用 ModelMapper 和 MapStruct 将类映射Delivery到类DeliveryDTO

首先我们来定义Delivery类和DeliveryDTO类:

public class Delivery {private UUID trackId;private LocalDate when;private String city;private String country;}public record DeliveryDTO(String id, String when, String city, String country) {}

使用映射结构:

1. 将 MapStruct 依赖项添加到您的项目中。对于Maven:

<dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>${org.mapstruct.version}</version>
</dependency>

2.创建映射接口:

@Mapperpublic interface DeliveryMapper {@Mapping(target = "trackId", source = "id")Delivery toEntity(DeliveryDTO dto);@Mapping(target = "id", source = "trackId")DeliveryDTO toDTO(Delivery entity);}

3. 执行映射:

DeliveryMapper mapper = Mappers.getMapper(DeliveryMapper.class);
Delivery delivery = new Delivery(UUID.randomUUID(), LocalDate.now(), "Salvador", "Brazil");
DeliveryDTO dto = this.mapper.toDTO(delivery);
Delivery entity = this.mapper.toEntity(dto);

使用模型映射器:

1. 将 ModelMapper 依赖项添加到您的项目中。对于Maven:

<dependency><groupId>org.modelmapper</groupId><artifactId>modelmapper</artifactId><version>${org.modelmapper.version}</version>
</dependency>

2. 创建一个新的ModelMapper实例:

ModelMapper modelMapper = new ModelMapper();

3. 设置配置和转换器: 不幸的是,它ModelMapper不适用于记录。因此,我们必须首先将其转换为类,并创建并定义一个转换器并UUID键入,LocalDate如下面的代码所示。


ModelMapper mapper = new ModelMapper();mapper.getConfiguration().setFieldMatchingEnabled(true).setFieldAccessLevel(Configuration.AccessLevel.PRIVATE);Converter<String, UUID> uuidConverter = new AbstractConverter<>() {@Overrideprotected UUID convert(String source) {return UUID.fromString(source);}};Converter<String, LocalDate> localDateConverter = new AbstractConverter<>() {@Overrideprotected LocalDate convert(String source) {return LocalDate.parse(source);}
};mapper.addConverter(uuidConverter);
mapper.addConverter(localDateConverter);TypeMap<DeliveryDTO, Delivery> typeMap = this.mapper.createTypeMap(DeliveryDTO.class, Delivery.class);
typeMap.addMappings(mapping -> mapping.using(uuidConverter).map(DeliveryDTO::id, Delivery::setTrackId));

4. 执行映射:

Delivery delivery = new Delivery(UUID.randomUUID(), LocalDate.now(), "New York", "USA");
DeliveryDTO deliveryDTO = modelMapper.map(delivery, DeliveryDTO.class);

        在本次动手实践中,我们了解了如何使用 ModelMapper 和 MapStruct 将Delivery类映射到类DeliveryDTO。这两个框架都使这种映射变得毫不费力,并允许开发人员专注于构建应用程序的核心逻辑,而不是花费时间进行手动映射。

结论

        ModelMapper 和 MapStruct 等自动映射器比手动映射具有显着优势,可以提高生产率、可维护性并减少数据映射中的错误。选择合适的映射器取决于您项目的具体需求。尽管如此,ModelMapper 和 MapStruct 仍然是强大的工具,可以简化复杂的映射场景,并帮助开发人员交付更高效、更可维护的 Java 应用程序。


http://www.ppmy.cn/news/1022601.html

相关文章

将vsCode 打开的多个文件分行(栏)排列,实现全部显示,便于切换文件

目录 1. 前言 2. 设置VsCode 多文件分行(栏)排列显示 1. 前言 主流编程IDE几乎都有排列切换选择所要查看的文件功能&#xff0c;如下为Visual Studio 2022的该功能界面&#xff1a; 图 1 图 2 当在Visual Studio 2022打开很多文件时&#xff0c;可以按照图1、图2所示找到自…

ThreadLocal的内存泄漏是怎么发生的

前言 在分析ThreadLocal导致的内存泄露前&#xff0c;需要普及了解一下内存泄露、强引用与弱引用以及GC回收机制&#xff0c;这样才能更好的分析为什么ThreadLocal会导致内存泄露呢&#xff1f;更重要的是知道该如何避免这样情况发生&#xff0c;增强系统的健壮性。 内存泄露 …

无涯教程-Perl - getpwnam函数

描述 此函数基于EXPR指定的用户名,从/etc/passwd文件提取的列表context中返回字段列表。通常这样使用- ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) getpwnam($user); 在标量context中,返回数字用户ID。如果尝试访问整个/etc/passwd文件,则应使用getpwent…

解决VScode远程服务器时opencv和matplotlib无法直接显示图像的问题

解决VScode远程服务器时opencv和matplotlib无法直接显示图像的问题 1、本方案默认本地已经安装了VScode与MobaXterm2、在服务器端3、在本地端安装MobaXterm4、测试5、opencv显示测试&#xff08;测试过程中需保持MobaXterm开启的状态&#xff09;6、 matplotlib显示测试&#x…

vs2022+qt6.24+Cef编译

1.QCefView源码下载地址 https://github.com/cefview/qcefview2.目录层级关系如下&#xff1a; 3.下载CefViewCore git pull --regit pull --recurse-submodules上面命令失败直接用下面的命令 git clone gitgithub.com:CefView/CefViewCore.git4.编译QCefView准备工作 a.准…

(四)ESP32基于MicroPython平台——驱动TFT-1.44寸屏(SPI)

一. 所需器件工具 1.ESP32-CAM开发板。开发板购买链接 2.TFT-1.44寸屏。TFT-1.44寸屏购买链接 二. 硬件SPI接口简介 有两个硬件SPI通道允许更快的传输速率&#xff08;最高80Mhz&#xff09;。 HSPI (id1) VSPI (id2) sck 14 18 mosi 13 23 miso 12 19 三. TFT-1.4…

【torch.nn : Pooling Layers】

文章目录 MaxPool2dAvgPool2dAdaptiveAvgPool2dMaxUnpool2d MaxPool2d CLASS torch.nn.MaxPool2d(kernel_size, strideNone, padding0, dilation1, return_indicesFalse, ceil_modeFalse)功能&#xff1a; 在由几个输入平面组成的输入信号上应用2D最大池化。 举个简单的例子&a…

YOLOv5、YOLOv8改进:添加ShuffleAttention注意力机制

广泛应用的注意力机制主要有空间注意力机制和通道注意力机制&#xff0c;其目的分别是捕捉像素级的成对关系和通道依赖关系。虽然将两种机制融合在一起可以获得比单独更好的性能&#xff0c;但计算开销不可避免。因而&#xff0c;本文提出Shuffle Attetion&#xff0c;即SA&…