Lombok 与 MapStruct 的结合使用指南!

举报
bug菌 发表于 2024/12/31 09:53:25 2024/12/31
【摘要】 🏆本文收录于「滚雪球学SpringBoot」专栏,专业攻坚指数级提升持续更新中,up!up!up!!欢迎点赞&&收藏&&订阅。@TOC 📝 前言:Lombok 和 MapStruct 的强强联手在 Java 开发中,Lombok 是一个非常流行的库,用于简化 Java 代码,尤其是在处理 Getter/Setter、Builder 等样板代码时。MapStruct 则是一个用于对象映射的...

🏆本文收录于「滚雪球学SpringBoot」专栏,专业攻坚指数级提升持续更新中,up!up!up!!欢迎点赞&&收藏&&订阅。

@TOC

📝 前言:Lombok 和 MapStruct 的强强联手

在 Java 开发中,Lombok 是一个非常流行的库,用于简化 Java 代码,尤其是在处理 Getter/SetterBuilder 等样板代码时。MapStruct 则是一个用于对象映射的高效工具,能够在编译期间生成类型安全的对象映射代码。

将这两个工具结合使用,可以大幅提升开发效率,但在实际项目中,Lombok 和 MapStruct 的结合使用可能会面临一些挑战。本文将详细介绍 Lombok 和 MapStruct 的结合使用方法,以及常见问题的解决方案。


📖 目录

  1. 🎯 Lombok 与 MapStruct 的基本功能介绍
  2. 🛠️ Lombok 与 MapStruct 的结合使用
    • 使用 Lombok 的 Getter/Setter
    • 使用 Lombok 的 Builder
  3. 🔍 常见问题与解决方案
    • Lombok 的 Builder 与 MapStruct 的兼容问题
    • 多层级对象映射问题
  4. 进阶用法:MapStruct 的自定义映射与转换
  5. 💡 总结与最佳实践

🎯 Lombok 与 MapStruct 的基本功能介绍

1️⃣ Lombok 简介

Lombok 是一个 Java 注解处理器,通过注解的方式自动生成样板代码,常用注解包括:

  • @Getter / @Setter:生成 getter 和 setter 方法。
  • @Builder:生成 Builder 模式代码。
  • @ToString / @EqualsAndHashCode:生成 toStringequalshashCode 方法。
  • @AllArgsConstructor / @NoArgsConstructor:生成全参和无参构造函数。

示例:使用 Lombok 简化数据类

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class UserDTO {
    private Long id;
    private String name;
    private String email;
}

2️⃣ MapStruct 简介

MapStruct 是一个用于对象映射的代码生成工具,能在编译时生成高效的、类型安全的对象转换代码。常用的注解包括:

  • @Mapper:定义映射接口。
  • @Mapping:指定字段之间的映射关系。
  • @InheritConfiguration:继承已有的映射配置。
  • @MappingTarget:支持对象更新。

示例:使用 MapStruct 实现对象映射

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper
public interface UserMapper {
    @Mapping(source = "email", target = "contactEmail")
    UserEntity toEntity(UserDTO dto);

    UserDTO toDTO(UserEntity entity);
}

🛠️ Lombok 与 MapStruct 的结合使用

1️⃣ 使用 Lombok 的 Getter/Setter

当 Lombok 的 @Getter@Setter 用于数据类时,MapStruct 可以直接调用这些生成的方法进行映射,无需额外配置。

代码示例:

import lombok.Data;

// DTO 类
@Data
public class UserDTO {
    private Long id;
    private String name;
    private String email;
}

// Entity 类
@Data
public class UserEntity {
    private Long id;
    private String name;
    private String contactEmail;
}

// MapStruct 映射接口
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;

@Mapper
public interface UserMapper {
    @Mapping(source = "email", target = "contactEmail")
    UserEntity toEntity(UserDTO dto);

    @Mapping(source = "contactEmail", target = "email")
    UserDTO toDTO(UserEntity entity);
}

运行结果:

  • MapStruct 能直接调用 Lombok 自动生成的 Getter 和 Setter 方法。
  • 不需要手动实现映射逻辑。

2️⃣ 使用 Lombok 的 Builder

Lombok 的 @Builder 注解可以与 MapStruct 结合使用,但需要额外配置。

代码示例:

import lombok.Builder;
import lombok.Data;

// DTO 类
@Data
@Builder
public class UserDTO {
    private Long id;
    private String name;
    private String email;
}

// Entity 类
@Data
@Builder
public class UserEntity {
    private Long id;
    private String name;
    private String contactEmail;
}

// MapStruct 映射接口
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 = "email", target = "contactEmail")
    UserEntity toEntity(UserDTO dto);

    @Mapping(source = "contactEmail", target = "email")
    UserDTO toDTO(UserEntity entity);
}

注意事项:

  1. 默认情况下,MapStruct 会使用 Setter 和 Getter 方法。
  2. 当类使用了 @Builder,且没有 Setter 方法时,需要告诉 MapStruct 使用 Builder 进行映射。

解决方法:使用 Builder 映射配置

@Mapper(builder = @Mapper.Builder(disableBuilder = false))
public interface UserMapper {
    @Mapping(source = "email", target = "contactEmail")
    UserEntity toEntity(UserDTO dto);

    @Mapping(source = "contactEmail", target = "email")
    UserDTO toDTO(UserEntity entity);
}

🔍 常见问题与解决方案

1️⃣ Lombok 的 Builder 与 MapStruct 不兼容

问题描述:
当使用 @Builder 注解时,Lombok 会移除 Setter 方法,这可能导致 MapStruct 无法调用 Setter 方法进行映射。

解决方案:

  • 在 MapStruct 的 @Mapper 注解中,显式启用 Builder 映射。
@Mapper(builder = @Mapper.Builder(disableBuilder = false))

2️⃣ 多层级对象映射问题

问题描述:
如果对象中包含嵌套对象,Lombok 和 MapStruct 的结合可能会导致嵌套对象无法正确映射。

解决方案:

  • 在 MapStruct 中定义嵌套对象的映射规则。
@Mapper
public interface UserMapper {
    @Mapping(source = "address.street", target = "addressStreet")
    UserEntity toEntity(UserDTO dto);
}

进阶用法:MapStruct 的自定义映射与转换

1️⃣ 自定义字段转换

当需要对某些字段进行特殊处理时,可以使用 MapStruct 的 @Mapping 注解,并编写自定义方法。

示例:格式化日期

@Mapper
public interface UserMapper {
    @Mapping(source = "birthDate", target = "birthDate", dateFormat = "yyyy-MM-dd")
    UserEntity toEntity(UserDTO dto);
}

2️⃣ 使用默认方法

在 MapStruct 接口中,可以定义默认方法,用于处理复杂的字段映射逻辑。

示例:自定义字段处理

@Mapper
public interface UserMapper {

    @Mapping(source = "email", target = "contactEmail")
    UserEntity toEntity(UserDTO dto);

    default String mapEmail(String email) {
        return email != null ? email.toLowerCase() : null;
    }
}

💡 总结与最佳实践

  1. 直接映射 Getter/Setter:
    Lombok 的 @Data 和 MapStruct 的 @Mapper 配合使用时,可以直接调用生成的 Getter 和 Setter,无需额外配置。

  2. 使用 Builder 模式:
    如果类使用了 @Builder 注解,需要在 MapStruct 的 @Mapper 中启用 Builder 支持。

  3. 嵌套对象映射:
    对于多层嵌套对象,推荐单独定义嵌套对象的映射规则。

  4. 自定义字段转换:
    使用 MapStruct 的 @Mapping 或默认方法,实现复杂的字段转换逻辑。


通过将 LombokMapStruct 结合使用,可以极大简化对象映射和样板代码的编写,提高开发效率。在项目中,合理搭配这两种工具,能够让你的代码更加简洁高效!🚀✨

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。