MapStruct 1.5.5类型转换(复杂对象映射)

林欢喜 Java经验 发布时间:2026-01-14 10:17:14 阅读数:18446 1
下文笔者讲述MapStruce1.5.5的简介说明,如下所示

MapStruce1.5.5简介

MapStruct 1.5.5 是一款编译期的 Java 类型映射工具,
      核心用于解决 POJO / 实体 / DTO 之间的对象转换问题,
      相比反射式工具(如 BeanUtils):
核心优势:
      编译期生成类型安全的映射代码,无运行时反射开销,
        性能高;
       编译时即可发现字段映射错误,避免运行时问题。
核心能力:
       支持基础字段映射、嵌套对象递归映射、
        自定义转换(日期 / 枚举 / 多字段组合)、
         集合(list/Set)映射,
         可集成 Spring 容器,
       兼容 Lombok。
使用方式:
        通过 @Mapper 定义映射接口,
               @Mapping 注解指定字段映射规则,
               框架自动生成实现类,
                 无需手动编写转换代码。
=================================================
MapStruct 1.5.5 是编译期映射工具,
        性能高、类型安全,
        替代手动编写转换代码。
核心通过注解定义映射规则,
       支持基础/嵌套/自定义/集合
       等多场景对象转换。
兼容 Spring 和 Lombok,
      是Java 开发中对象转换的主流选择

MapStruct 1.5.5使用方法

引入maven依赖

<!-- MapStruct 核心依赖 -->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version>
</dependency>
<!-- 注解处理器(编译期生成实现类) -->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>1.5.5.Final</version>
    <scope>provided</scope>
</dependency>
<!-- Lombok 可选(如果用了Lombok,需注意版本兼容) -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
    <scope>provided</scope>
</dependency>

场景1:嵌套对象映射(基础)

当有以下嵌套结构的实体和 DTO:
 
// 子实体
@Data
public class Address {
    private Long id;
    private String province;
    private String city;
}

// 主实体
@Data
public class User {
    private Long userId;
    private String userName;
    private Integer age;
    private Address userAddress; // 嵌套对象
}

// 子DTO
@Data
public class AddressDTO {
    private Long addressId; // 字段名与实体不一致
    private String province;
    private String city;
}

// 主DTO
@Data
public class UserDTO {
    private Long id; // 字段名与实体不一致
    private String name; // 字段名与实体不一致
    private Integer age;
    private AddressDTO address; // 嵌套DTO
} 

映射器编写:
 
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;

// componentModel = "spring" 表示生成的实现类交给Spring管理,也可以用默认的 "default"
@Mapper(componentModel = "spring")
public interface UserMapper {
    // 单例实例(非Spring环境使用)
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    // 主对象映射:指定字段映射关系,嵌套对象会自动递归映射(字段名匹配时)
    @Mapping(source = "userId", target = "id")
    @Mapping(source = "userName", target = "name")
    @Mapping(source = "userAddress", target = "address") // 显式指定嵌套对象映射(可选,字段名匹配时可省略)
    UserDTO userToUserDTO(User user);

    // 嵌套对象映射:处理字段名不一致的情况
    @Mapping(source = "id", target = "addressId")
    AddressDTO addressToAddressDTO(Address address);

    // 反向映射(可选)
    @Mapping(source = "id", target = "userId")
    @Mapping(source = "name", target = "userName")
    @Mapping(source = "address", target = "userAddress")
    User userDTOToUser(UserDTO userDTO);
}
   
 场景2:自定义复杂转换(如枚举、日期、多字段组合)
假设需要将 `User` 中的 `age` 和 `userName` 组合成 `UserDTO` 的 `desc` 字段,且处理日期类型转换:
 
//扩展User和UserDTO
@Data
public class User {
    // 原有字段...
    private Date createTime; // 日期类型
    private Integer age;
    private String userName;
}

@Data
public class UserDTO {
    // 原有字段...
    private String createTimeStr; // 格式化后的日期字符串
    private String desc; // 组合字段:姓名+年龄
}

// 映射器增强
@Mapper(componentModel = "spring", imports = {SimpleDateFormat.class})
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    // 自定义字段转换:使用expression或qualifiedByName
    @Mapping(source = "userId", target = "id")
    @Mapping(source = "userName", target = "name")
    @Mapping(source = "userAddress", target = "address")
    @Mapping(source = "createTime", target = "createTimeStr", dateFormat = "yyyy-MM-dd HH:mm:ss") // 日期格式化
    @Mapping(target = "desc", qualifiedByName = "buildDesc") // 自定义方法转换
    UserDTO userToUserDTO(User user);

    // 自定义转换方法(命名规则:@Named 注解匹配 qualifiedByName)
    @Named("buildDesc")
    default String buildDesc(User user) {
        return user.getUserName() + ",年龄:" + (user.getAge() == null ? "未知" : user.getAge());
    }

    // 也可以用expression(直接写Java代码)
    // @Mapping(target = "desc", expression = "java(user.getUserName() + \",年龄:\" + (user.getAge() == null ? \"未知\" : user.getAge()))")

    // 嵌套对象映射(不变)
    @Mapping(source = "id", target = "addressId")
    AddressDTO addressToAddressDTO(Address address);
}

场景3:集合映射(复杂对象列表)

MapStruct支持集合(List/Set/Map)自动映射
    只需定义单个对象的映射方法,
    集合映射会自动生成:
 
@Mapper(componentModel = "spring")
public interface UserMapper {
    // 单个对象映射(基础)
    @Mapping(source = "userId", target = "id")
    @Mapping(source = "userName", target = "name")
    UserDTO userToUserDTO(User user);

    // 集合映射:无需手动实现,MapStruct自动生成
    List<UserDTO> userListToUserDTOList(List<User> userList);
    
    // Set/Map同理
    Set<UserDTO> userSetToUserDTOSet(Set<User> userSet);
    Map<Long, UserDTO> userMapToUserDTOMap(Map<Long, User> userMap);
}


@SpringBootTest
public class MapStructTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void testComplexMapping() {
        // 构造测试数据
        Address address = new Address();
        address.setId(1L);
        address.setProvince("北京");
        address.setCity("朝阳区");

        User user = new User();
        user.setUserId(1001L);
        user.setUserName("张三");
        user.setAge(25);
        user.setUserAddress(address);
        user.setCreateTime(new Date());

        // 转换
        UserDTO userDTO = userMapper.userToUserDTO(user);
        System.out.println(userDTO);
        // 输出示例:UserDTO(id=1001, name=张三, age=25, address=AddressDTO(addressId=1, province=北京, city=朝阳区), createTimeStr=2026-01-14 10:00:00, desc=张三,年龄:25)
    }
}

MapStruct关键注意事项

1. MapStruct是编译期生成实现类,
                   而非运行时反射,
                   因此性能高、类型安全,编译时就能发现字段映射错误。
2. 嵌套对象映射时,
                 若字段名不一致,
                需显式定义嵌套对象的映射方法(如 `addressToAddressDTO`)。
3. 自定义转换方法可以是 `default` 方法(MapStruct 1.4+ 支持)
               也可以单独写一个转换工具类,通过 `uses` 属性引入:
    
   @Mapper(componentModel = "spring", uses = {CustomConverter.class})
   public interface UserMapper { ... }
   
4. 版本兼容:
     MapStruct 1.5.5 对 Lombok 兼容性较好,
     但需确保 Lombok 版本 ≥ 1.18.16,避免编译期生成代码异常。

==============================================================
1. 复杂对象映射核心:通过 `@Mapping` 指定字段映射关系,
                                嵌套对象可自动递归映射,字段名不一致时
                                需显式定义嵌套对象的映射方法。
2. 自定义转换:使用`dateFormat` 处理日期、
                       `qualifiedByName`/`expression` 处理多字段组合/特殊逻辑,
                       `uses` 引入外部转换工具类。
3. 集合映射:只需定义单个对象的映射方法,
                       MapStruct 自动生成集合映射的实现,
                      无需手动编写循环。

MapStruct 1.5.5 版本的复杂对象映射核心是“约定优于配置”,
                  大部分场景下只需少量注解即可完成映射,
                   仅在特殊转换时需自定义逻辑,
                  既高效又保证代码的可维护性
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaJingYan/202601/17683570698537.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者