mapstruct中的@Mapper注解详解

在MapStruct中,@Mapper注解是核心注解之一,用于标记一个接口或抽象类为MapStruct的映射器(Mapper)。MapStruct会在编译时自动生成该接口的实现类,完成对象之间的属性映射。以下是对@Mapper注解的详细解析:


1. 基本用法

@Mapper注解可以单独使用,也可以配合其他属性进行配置。以下是一个简单的示例:

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;@Mapper
public interface UserMapper {UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);@Mapping(source = "username", target = "name")UserDTO toUserDTO(User user);
}
  • @Mapper:标记接口为MapStruct的映射器。
  • Mappers.getMapper(UserMapper.class):获取MapStruct自动生成的映射器实例。
  • @Mapping:指定属性映射规则(例如将Userusername属性映射到UserDTOname属性)。

2. 常用属性

@Mapper注解支持多种属性,用于配置映射器的行为:

(1) componentModel

指定生成的映射器实现类的组件模型,便于与其他框架(如Spring、CDI)集成。

  • 可选值
    • default:默认模型,不依赖任何框架。
    • spring:生成的映射器实现类会带有@Component注解,便于Spring管理。
    • cdi:生成的映射器实现类会带有@ApplicationScoped注解,便于CDI管理。
    • jsr330:生成的映射器实现类会带有@javax.inject.Named@javax.inject.Singleton注解。

示例

@Mapper(componentModel = "spring")
public interface UserMapper {UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);// ...
}
(2) uses

指定其他映射器或工具类,用于在映射过程中调用。

示例

@Mapper(uses = {DateMapper.class})
public interface UserMapper {UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);// ...
}
(3) implementationNameimplementationPackage
  • implementationName:指定生成的映射器实现类的名称(默认为接口名+Impl)。
  • implementationPackage:指定生成的映射器实现类的包名(默认为接口所在包)。

示例

@Mapper(implementationName = "CustomUserMapperImpl", implementationPackage = "com.example.mappers")
public interface UserMapper {// ...
}
(4) unmappedTargetPolicy

指定当目标对象有未映射的属性时的处理策略。

  • 可选值
    • ERROR:抛出异常(默认值)。
    • WARN:生成警告日志。
    • IGNORE:忽略未映射的属性。

示例

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface UserMapper {// ...
}
(5) injectionStrategy

指定依赖注入的策略。

  • 可选值
    • FIELD:通过字段注入(默认值)。
    • CONSTRUCTOR:通过构造函数注入。
    • METHOD:通过方法注入。

示例

@Mapper(componentModel = "spring", injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface UserMapper {// ...
}

3. 高级用法

(1) 结合@MapperConfig

可以通过@MapperConfig定义全局配置,然后在@Mapper中引用。

示例

@MapperConfig(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
public interface CommonMapperConfig {
}@Mapper(config = CommonMapperConfig.class)
public interface UserMapper {// ...
}
(2) 自定义方法

可以在映射器接口中定义自定义方法,MapStruct会调用这些方法完成复杂的映射逻辑。

示例

@Mapper
public interface UserMapper {UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);@Mapping(target = "fullName", expression = "java(user.getFirstName() + \" \" + user.getLastName())")UserDTO toUserDTO(User user);default String formatDate(Date date) {// 自定义日期格式化逻辑return new SimpleDateFormat("yyyy-MM-dd").format(date);}
}

4. 注意事项

  1. 依赖配置

    • 确保项目中包含MapStruct的依赖和注解处理器(mapstructmapstruct-processor)。
    • 如果使用Lombok,确保Lombok的版本兼容,并在构建工具(如Maven或Gradle)中正确配置。
  2. 映射规则

    • 如果源对象和目标对象的属性名相同,MapStruct会自动映射。
    • 如果属性名不同,需要通过@Mapping注解显式指定。
  3. 性能

    • MapStruct生成的映射代码是类型安全的,且在编译时完成,性能优于运行时反射的映射工具(如Apache Commons BeanUtils)。

5. 总结

@Mapper注解是MapStruct的核心,通过它可以:

  • 定义映射器接口。
  • 配置映射器的行为(如组件模型、未映射属性的处理策略等)。
  • 结合其他注解(如@Mapping)完成复杂的属性映射。
  • 与其他框架(如Spring)无缝集成。

通过合理使用@Mapper注解及其属性,可以大大简化对象之间的映射逻辑,提高开发效率和代码质量。

6. 编译异常处理

针对MapStruct项目编译异常问题,可从依赖配置、IDE设置、代码规范及版本兼容性四个维度进行排查和解决,以下是具体分析和建议:

依赖配置问题
  • 现象:缺少必要的注解处理器依赖,如org.mapstruct:mapstruct-processor,导致编译时无法生成Mapper类。
  • 解决方案
    • Maven项目:在pom.xml中添加MapStruct核心库和处理器依赖,例如:
<dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>1.5.3.Final</version>
</dependency>
<dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>1.5.3.Final</version><scope>provided</scope>
</dependency>
- **Gradle项目**:在`build.gradle`中添加:
implementation 'org.mapstruct:mapstruct:1.5.3.Final'
annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.3.Final'
IDE设置问题
  • 现象:IDE未启用注解处理器或缓存异常,导致编译时无法正确处理MapStruct注解。
  • 解决方案
    • IntelliJ IDEA:打开“File”菜单,选择“Settings”,导航至“Build, Execution, Deployment” -> “Compiler” -> “Annotation Processors”,勾选“Enable annotation processing”选项,并清理IDE缓存后重新构建项目。
代码规范问题
  • 现象:Mapper接口定义错误,如方法签名不匹配或缺少必要注解,导致编译失败。
  • 解决方案
    • 验证Mapper接口:确保接口符合MapStruct规范,例如:
@Mapper
public interface UserMapper {UserDto userToUserDto(User user);
}
- **检查属性映射**:如果源对象和目标对象的属性名不同,需要通过`@Mapping`注解显式指定,例如:
@Mapper
public interface UserMapper {@Mapping(source = "username", target = "name")UserDto userToUserDto(User user);
}
版本兼容性问题
  • 现象:MapStruct版本与其他依赖(如Lombok)不兼容,导致编译异常。
  • 解决方案
    • 升级MapStruct版本:尝试升级至最新稳定版本,例如:
<dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>1.6.0.Final</version>
</dependency>
- **解决Lombok冲突**:如果项目中同时使用Lombok和MapStruct,特别是使用Lombok的`@Builder`注解时,可能导致`@AfterMapping`不生效。对于Lombok版本1.18.16或更高版本,需添加`lombok-mapstruct-binding`依赖:
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok-mapstruct-binding</artifactId><version>0.2.0</version>
</dependency>
其他可能的问题及解决方案
  • 未映射的目标属性:检查源对象和目标对象,确保存在对应的属性,或使用@Mapping(target = "property", ignore = true)忽略不需要映射的属性。
  • 枚举类型映射:自定义映射方法,例如:
@Mapper
public interface EnumConverter {default TargetEnum toTargetEnum(SourceEnum sourceEnum) {if (sourceEnum == null) {return null;}switch (sourceEnum) {case SOURCE_VALUE1:return TargetEnum.TARGET_VALUE1;case SOURCE_VALUE2:return TargetEnum.TARGET_VALUE2;default:throw new IllegalArgumentException("Unknown enum type: " + sourceEnum);}}
}
  • 集合类型映射:使用@IterableMapping注解明确指定集合类型的映射方式。
  • 循环引用问题:使用@Context注解通过传递上下文对象来避免无限递归。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp+vue2+h5图片下载保存,微信浏览器、非微信浏览器

小程序端 onDown() {// 检查相册权限uni.authorize({scope: scope.writePhotosAlbum,success: () > {this.downloadImage();},fail: () > {uni.showToast({title: "请授权相册权限",icon: "none"});}}); }, downloadImage() {common.request(post, …

NumPy 与 OpenCV 版本兼容性深度解析:底层机制与解决方案

在计算机视觉项目中&#xff0c;NumPy 和 OpenCV 的兼容性问题常被低估&#xff0c;实则暗藏复杂的技术陷阱。下面从底层机制深入剖析核心兼容性问题及解决方案&#xff1a; 一、内存布局冲突&#xff1a;数组连续性陷阱 问题本质&#xff1a; OpenCV 的 C 内核要求 连续内存块…

基于SpringBoot利用死信队列解决RabbitMQ业务队列故障重试无效场景问题

基于SpringBoot利用死信队列解决RabbitMQ业务队列故障重试无效场景问题 解决方案项目实战1、生产者服务1.1、RabbitConfig定义相关交换机及死信队列等配置数据1.2、TestController测试接口Controller 2、消费者服务2.1 BusinessQueueConsumer业务队列监听器2.2 DeadLetterConsu…

西安java面试总结1

这是我第二次的面试。其实第一次也算不上面试&#xff0c;去了让我手写了几道题&#xff0c;三道算法题&#xff0c;一道SQL题&#xff0c;两道逻辑思维题&#xff0c;做完之后也没看我的解答&#xff0c;随便看了一眼简历&#xff0c;觉得我是大二的&#xff0c;大三还有课&am…

【redis】线程IO模型

Redis线程IO模型 总结&#xff1a;在redis5.0及之前&#xff0c;redis线程io模型是单线程。那么Redis单线程如何处理那么多的并发客户端连接的&#xff1f;原因两点&#xff1a;1&#xff09;非阻塞io 2&#xff09;多路复用&#xff08;事件轮询&#xff09; 以下&#xff0…

进程间通信详解(三):Linux进程信号深度解析

文章目录 一、Linux进程信号核心概念1.1 信号本质1.2 关键术语1.3 Linux 信号机制的核心流程&#xff1a; 二、信号产生机制全景2.1 通过终端按键产生信号2.1.1 基本操作 2.2 调用系统命令向进程发信号2.2.1 kill 命令&#xff1a;向指定进程发送信号2.2.2 killall 命令&#x…

C++ 日志系统实战第五步:日志器的设计

全是通俗易懂的讲解&#xff0c;如果你本节之前的知识都掌握清楚&#xff0c;那就速速来看我的项目笔记吧~ 本文项目代码编写收尾&#xff01; 日志器类 (Logger) 设计&#xff08;建造者模式&#xff09; 日志器主要用于和前端交互。当我们需要使用日志系统打印 log 时&…

Spring Boot + MyBatis日志前缀清除方法

在 Spring Boot 结合 MyBatis 的应用中&#xff0c;清空日志前缀&#xff08;如 > 、< 等&#xff09;需要通过 自定义 MyBatis 的日志实现 或 修改日志模板 来实现。以下是两种常用方法&#xff1a; 方法 1&#xff1a;自定义 MyBatis 日志实现&#xff08;推荐&#xf…

【消息队列】——如何实现消息保序

目录 一、哪些场景需要消息保序?二、如何实现消息保序?三、保序消息的常见问题和应对策略3.1、重复消息3.2、节点故障3.3、分区扩容四、小结本文来源:极客时间vip课程笔记 一、哪些场景需要消息保序? 消息保序问题指的是,在通过消息中间件传递消息过程中,我们希望消费者收…

Transformer模型详解

Transformer Transformer真是个细节满满的框架呢&#xff0c;大三读到根本不敢看&#xff0c;考研复试前看了看&#xff0c;以为懂了其实差得还远&#xff0c;两个多月前看了&#xff0c;还是一知半解&#xff0c;如今终于经过细细分析&#xff0c;算是知道了Transformer的基本…

火山引擎发布豆包大模型 1.6 与视频生成模型 Seedance 1.0 pro

6 月 11 日&#xff0c;在火山引擎 FORCE 原动力大会上&#xff0c;字节跳动旗下火山引擎正式发布豆包大模型 1.6、豆包・视频生成模型 Seedance 1.0 pro、豆包・语音播客模型&#xff0c;豆包・实时语音模型也在火山引擎全量上线&#xff0c;豆包大模型家族已成为拥有全模态、…

PH热榜 | 2025-06-12

1. Atlas 标语&#xff1a;几秒钟内了解定价情况 介绍&#xff1a;获取即插即用的定价页面&#xff0c;让你轻松赚钱&#xff0c;不再辛苦操劳。 产品网站&#xff1a; 立即访问 Product Hunt&#xff1a; View on Product Hunt 关键词&#xff1a;Atlas, 定价快速, 插件式…

ChatGPT革命升级!o3-pro模型重磅发布:开启AI推理新纪元

2025年6月10日&#xff0c;OpenAI以一场低调而震撼的发布&#xff0c;正式推出了新一代推理模型o3-pro&#xff0c;这标志着人工智能在复杂问题解决领域的重大突破。作为ChatGPT Pro和Team订阅用户的专属工具&#xff0c;o3-pro不仅重新定义了AI的可靠性标准&#xff0c;更以其…

NVIDIA Isaac GR00T N1.5 适用于 LeRobot SO-101 机械臂

系列文章目录 目录 系列文章目录 前言 一、简介 二、详细教程 2.1 数据集准备 2.1.1 创建或下载您的数据集 2.1.2 配置模态文件 2.2 模型微调 2.3 开环评估 2.4 部署 &#x1f389; 快乐编程&#xff01;&#x1f4bb;&#x1f6e0;️ 立即开始&#xff01; 前言 一…

【编译工具】(自动化)自动化测试工具:如何让我的开发效率提升300%并保证代码质量?

目录 引言&#xff1a;自动化测试在现代开发中的关键作用 一、自动化测试金字塔&#xff1a;构建高效的测试策略 &#xff08;1&#xff09;测试金字塔模型 &#xff08;2&#xff09;各层级代表工具 二、前端自动化测试实战&#xff1a;Jest Cypress &#xff08;1&…

R语言缓释制剂QBD解决方案之一

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》缓释制剂包衣处方研究的R语言解决方案。 ER聚合物包衣处方优化研究 基于初步风险评估和初始可行性研究&#xff0c;进行带3个中心点的24-1分式析因DOE。药物的释放被识别为CQA。本研究的…

行为模式-命令模式

定义&#xff1a; 命令模式是一个高内聚的模式&#xff0c;其定义为&#xff1a;Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations.&#xff08;将一个请求封装成…

Ubuntu 24.04 上安装与 Docker 部署 Sentinel

Ubuntu 24.04 上安装与 Docker 部署 Sentinel 一、Sentinel 简介 Sentinel 是阿里巴巴开源的分布式系统流量控制组件&#xff0c;提供流量控制、熔断降级和系统负载保护等功能。它通过可视化控制台&#xff08;Dashboard&#xff09;实现实时监控和规则管理&#xff0c;是微服…

IP 地址查询在证券交易中的应用方式

网络安全保障与IP地址查询 证券交易平台存储着海量投资者的敏感信息以及巨额资金的交易数据&#xff0c;是网络攻击的重点目标。IP 地址查询在检测异常登录行为方面至关重要。例如&#xff0c;当一个账户短时间内先在国内某城市登录&#xff0c;随后又在境外 IP 地址发起交易操…

Flutter 常用组件详解:Text、Button、Image、ListView 和 GridView

Flutter 作为 Google 推出的跨平台 UI 框架&#xff0c;凭借其高效的渲染性能和丰富的组件库&#xff0c;已经成为移动应用开发的热门选择。本文将深入探讨 Flutter 中最常用的五个基础组件&#xff1a;Text、Button、Image、ListView 和 GridView&#xff0c;帮助开发者快速掌…