掌握MapStruct:Java 中高效数据映射的艺术

MapStruct 是一个 Java 注解处理器,用于在不同 Java Beans 或数据传输对象(DTOs)之间自动生成类型安全的映射代码。这是一个编译时映射框架,意味着它利用注解在编译时生成代码,从而提高了性能和减少了运行时的开销。

它适用于 Java 8 和更高版本。以下是一些 MapStruct 的基本使用示例:

1. 基本映射

假设你有两个简单的类 PersonPersonDTO,需要将 Person 实体映射到 PersonDTO 数据传输对象。

Person.java

java 复制代码
public class Person {
    private String name;
    private int age;
    // getters and setters
}

PersonDTO.java

java 复制代码
public class PersonDTO {
    private String name;
    private int age;
    // getters and setters
}

PersonMapper.java

java 复制代码
@Mapper
public interface PersonMapper {
    PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
    PersonDTO personToPersonDTO(Person person);
}

2. 复杂类型映射

如果你的对象包含复杂类型或自定义类型,MapStruct 也可以处理这些。

Address.java

java 复制代码
public class Address {
    private String street;
    private String city;
    // getters and setters
}

Person.java (现在包含 Address)

java 复制代码
public class Person {
    private String name;
    private int age;
    private Address address;
    // getters and setters
}

PersonDTO.java (同样包含 Address)

java 复制代码
public class PersonDTO {
    private String name;
    private int age;
    private String street;
    private String city;
    // getters and setters
}

PersonMapper.java

java 复制代码
@Mapper
public interface PersonMapper {
    PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
    
    @Mapping(source = "address.street", target = "street")
    @Mapping(source = "address.city", target = "city")
    PersonDTO personToPersonDTO(Person person);
}

3. 使用表达式

有时,你可能需要在映射过程中使用自定义逻辑。MapStruct 允许你使用 Java 表达式来实现这一点。

Person.java

java 复制代码
public class Person {
    private String firstName;
    private String lastName;
    // getters and setters
}

PersonDTO.java

java 复制代码
public class PersonDTO {
    private String fullName;
    // getters and setters
}

PersonMapper.java

java 复制代码
@Mapper
public interface PersonMapper {
    PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);

    @Mapping(expression = "java(person.getFirstName() + ' ' + person.getLastName())", target = "fullName")
    PersonDTO personToPersonDTO(Person person);
}

4. 使用自定义方法

在某些情况下,你可能需要自定义映射逻辑。你可以在映射器接口中定义自己的方法来实现这一点。

Person.java

java 复制代码
public class Person {
    private String birthdate; // 假设这是一个字符串
    // getters and setters
}

PersonDTO.java

java 复制代码
public class PersonDTO {
    private LocalDate birthdate; // 在 DTO 中,我们使用 LocalDate
    // getters and setters
}

PersonMapper.java

java 复制代码
@Mapper
public interface PersonMapper {
    PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);

    @Mapping(target = "birthdate", source = "birthdate", dateFormat = "yyyy-MM-dd")
    PersonDTO personToPersonDTO(Person person);

    default LocalDate stringToLocalDate(String date) {
        return LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }
}

5. 映射集合

MapStruct 也能很好地处理集合映射。

PersonMapper.java

java 复制代码
@Mapper
public interface PersonMapper {
    PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);

    List<PersonDTO> personsToPersonDTOs(List<Person> persons);
}

6. 使用依赖注入

如果你使用 Spring 或类似框架,可以将 MapStruct 与依赖注入框架结合使用。

PersonMapper.java

java 复制代码
@Mapper(componentModel = "spring")
public interface PersonMapper {
    PersonDTO personToPersonDTO(Person person);
}

使用 componentModel = "spring",MapStruct 将生成一个 Spring 组件,可以被注入到你的服务中。

7. 更新现有对象

MapStruct 也可以用于更新现有对象,而不是创建新的。

PersonMapper.java

java 复制代码
@Mapper
public interface PersonMapper {
    void updatePersonFromDTO(PersonDTO personDto, @MappingTarget Person person);
}

这个方法将会根据 PersonDTO 中的数据更新一个已存在的 Person 对象,而不是创建一个新的。

8. 多源映射

你可以从多个源对象映射到一个目标对象。

Address.java

java 复制代码
public class Address {
    private String city;
    // getters and setters
}

PersonDTO.java

java 复制代码
public class PersonDTO {
    private String name;
    private String city;
    // getters and setters
}

PersonMapper.java

java 复制代码
@Mapper
public interface PersonMapper {
    @Mapping(source = "person.name", target = "name")
    @Mapping(source = "address.city", target = "city")
    PersonDTO personAndAddressToDTO(Person person, Address address);
}

总结

MapStruct 的主要优点是它提供了一种高效、类型安全且易于使用的方式来自动化对象间的数据映射。这使得它成为处理 Java 应用中数据转换的理想选择,尤其是在涉及复杂对象和多层架构的场景中。通过减少手写的样板代码和提供清晰的映射定义,MapStruct 可以帮助开发人员节省时间,减少错误,并提高代码的可维护性。

相关推荐
嘻哈∠※5 小时前
0061基于 SpringBoot 的投稿与稿件处理系统设计与实现
java·spring boot·后端
白狐_7986 小时前
408数据结构第8章:排序②——性质对比秒杀、场景选择与外部排序
java·数据结构·算法
zander2586 小时前
LeetCode 84:柱状图中的最大矩形——单调栈如何确定左右边界
java·数据结构·算法
码匠许师傅7 小时前
【C++ 面试真题】聊聊 C++ 的拷贝构造与拷贝赋值
java·c++·面试
捡田螺的小男孩8 小时前
什么是 Skill?手把手带你写一个简单有用的 Skill!
前端·后端·程序员
极创信息8 小时前
系统安全隐患全方位排查方案:标准化渗透测试全流程
java·opencv·struts·数据挖掘·eclipse·语音识别·hibernate
汉字萌萌哒9 小时前
2019CCF-CSP入门级C++试题解析
java·开发语言·c++
喜欢的名字被抢了9 小时前
程序出问题怎么查,以及如何让它不掉线
java·运维·数据库
数据知道10 小时前
反序列化漏洞:Java、PHP、Python 三条线各讲透
java·网络·python·安全·网络安全·php
2601_9499506310 小时前
Java 面试准备,用练题簿把“背过八股”变成“真正会答”
java·开发语言·面试·刷题·小程序推荐