了解如何在自动映射器 ModelMapper 和 MapStruct 之间进行选择,以提高生产力和可维护性,并减少数据映射中的错误。
在 Java 应用程序中, 数据映射 是一项常见任务,涉及将对象从一种类型转换为另一种类型。这个过程可能会变得复杂而乏味,特别是在处理大型嵌套类时。为了简化此任务,开发人员经常求助于自动映射框架。Java 中自动映射的两个流行选择是 ModelMapper 和 MapStruct。在本文中,我们将比较这些框架,并探讨为什么使用自动映射器比手动映射更有好处。
对自动制图器的需求
在深入比较之前,让我们先了解为什么自动映射器比手动映射更受青睐。以下是一些关键原因:
- 生产力:手动映射需要编写样板代码来在类之间传输数据。它可能非常耗时且容易出错,尤其是在具有许多类的应用程序中。自动映射器为您生成映射代码,节省宝贵的开发时间。
- 可维护性:随着应用程序的发展,类可能会发生变化,导致映射逻辑频繁更新。自动映射器会自动处理这些更改,从而降低更新期间引入错误的风险。
- 减少人为错误:手动映射涉及编写重复代码,这增加了人为错误的可能性。自动映射器确保类之间的映射一致且准确。
- 可读性:自动映射器提供了更干净、更简洁的映射代码,使开发人员更容易理解数据流。
- 灵活性:自动映射器通常允许自定义和配置来处理复杂的映射场景。
ModelMapper 与 MapStruct
ModelMapper 和 MapStruct 是 Java 生态系统中强大且广泛使用的映射框架。让我们根据各种因素对它们进行比较:
- 易于使用:ModelMapper 以其简单性和易用性而闻名。它自动映射具有相同名称和数据类型的字段。另一方面,MapStruct 要求开发人员编写显式映射接口,这可能导致更多的初始设置,但提供了对映射过程的更多控制。
- 性能:由于其编译时代码生成方法,MapStruct 的性能优于 ModelMapper。ModelMapper 依赖于反射,这可能会产生轻微的性能开销。
- 配置:ModelMapper提供了丰富的配置选项,支持复杂的映射场景。MapStruct 作为编译时映射器,需要显式映射接口,这既可以是优点(静态类型),也可以是缺点(更多初始设置)。
- 定制:两个框架都允许定制转换器来处理特定的映射情况。然而,ModelMapper 提供了更多的内置转换,并且在许多场景中需要更少的自定义转换器。
ModelMapper 和 MapStruct 都是 Java 中自动映射的绝佳选择,决定使用其中一种主要取决于项目的具体要求和偏好。
超越 DTO:自动映射器的各种用例
除了简单的DTO映射之外,自动映射器还可以通过多种方式使用。让我们探讨一些其他用例:
- 层之间的转换:自动映射器可以将域对象转换为 DTO、表示模型或应用程序层之间的任何其他数据转换。
- 遗留代码中的适配器和转换:在处理遗留代码库时,自动映射器可以充当适配器来弥合新旧类结构之间的差距。它们使得引入现代数据模型变得更容易,同时仍然支持现有的代码库。
- 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 应用程序。