MapStruct 对象转换使用方式

简介

MapStruct 是一种实体映射框架,用于生成类型安全的 Bean 映射类的 Java 注解处理器。只需定义一个 mapper 接口,在该接口中声明需要映射的方法。在编译过程中,MapStruct 就会生成该接口的实现。

注意:MapStruct 不是通过反射实现,而是通过使用纯 Java 的方法调用源对象和目标对象之间进行映射,因此效率很高。

与动态映射框架相比,MapStruct 具有以下优点:

  • 使用纯 Java 方法代替 Java 反射机制快速执行。
  • 编译时类型安全:只能映射彼此的对象和属性,不能映射一个 Order 实体到一个自定义 DTO 中等等。
  • 如果无法映射实体或属性,则在编译时清楚错误报告。

相关依赖

xml 复制代码
<properties>
  <lombok.version>1.18.30</lombok.version>
  <mapstruct.version>1.5.5.Final</mapstruct.version>
</properties>

<dependencies>
  <dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>${mapstruct.version}</version>
  </dependency>
</dependencies>

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>${maven-compiler-plugin.version}</version>
      <configuration>
        <annotationProcessorPaths>
          <path>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
          </path>
          <path>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${mapstruct.version}</version>
          </path>
        </annotationProcessorPaths>
      </configuration>
    </plugin>
  </plugins>
</build>

使用示例

这里通过创建 UserUserDTO 两个类进行进行相互转换

创建 User 类,代码如下:

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {

    /**
     * 用户编号
     */
    private Integer id;

    /**
     * 用户名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;
}

创建 UserDTO 类,代码如下:

java 复制代码
@Data
public class UserDTO {

    /**
     * 用户编号
     */
    private Integer userId;

    /**
     * 用户名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;
}

1、示例一

创建 UserConvert 接口,作为 User 相关的转换器,代码如下:

java 复制代码
@Mapper
public interface UserConvert {

    UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);
  
    /**
     * 将 User 对象转换为 UserDTO 对象
     *
     * @param user User 对象
     * @return UserDTO 对象
     */
    UserDTO toUserDTO(User user);
}

相关说明:

1、@Mapper 注解:用于声明该接口是一个 Map Struct Mapper 映射器。

2、UserConvert INSTANCE = Mappers.getMapper(UserConvert.class); 通过调用 Mappers.getMapper(Class<T> clazz) 方法,获取 MapStruct 帮助我们自动生成 UserConvert 实现类的对象。

测试代码如下:

java 复制代码
public class IssuesTest {

    @Test
    public void test01() {
        User user = new User(1001, "张三", 18);
        UserDTO userDTO = UserConvert.INSTANCE.toUserDTO(user);
        System.out.println("userDTO = " + userDTO);
    }
}

2、示例二

不同对象转换时,可能会存在属性不是完全映射的情况,例如:属性名不同等情况,可以通过使用 @Mapping 注解,配置对应的映射关系,如上述 User 类的 id 属性 和 UserDTO 类的 userId 属性,这两个属性名不能,从而无法将 User 类的 id 属性映射到 UserDTO 类的 userId 属性中。

此时修改 UserConvert 接口,代码如下:

java 复制代码
@Mapper
public interface UserConvert {

    UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);

    /**
     * 将 User 对象转换为 UserDTO 对象
     *
     * @param user User 对象
     * @return UserDTO 对象
     */
    @Mappings(value = {
            @Mapping(source = "id", target = "userId")
    })
    UserDTO toUserDTO02(User user);
}

相关说明:

1、@Mapping 注解的 source 属性需要设置源目标的属性,这里是将 User 转换为 UserDTO,所以设置为User 对象的 id 属性名。

2、@Mapping 注解的 target 属性需要设置目标对象的属性,这里是将 User 转换为 UserDTO,所以设置为 UserDTO 对象的 userId 属性名。

测试代码如下:

java 复制代码
public class IssuesTest {

    @Test
    public void test02() {
        User user = new User(1001, "张三", 18);
        UserDTO userDTO = UserConvert.INSTANCE.toUserDTO02(user);
        System.out.println("userDTO = " + userDTO);
    }
}

3、示例三

MapStruct 还支持将多个对象转换为一个对象,例如:需要将 User、Address对象转换为 UserDTO 对象。

创建 Address 对象,代码如下:

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Address {

    /**
     * 地址
     */
    private String addressName;
    
}

修改 UserDTO 对象,代码如下:

java 复制代码
@Data
public class UserDTO {

    /**
     * 用户编号
     */
    private Integer userId;

    /**
     * 用户名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 地址
     */
    private String address;
}

修改 UserConvert 接口,代码如下:

java 复制代码
@Mapper
public interface UserConvert {

    UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);

    /**
     * 将 User 对象转换为 UserDTO 对象
     *
     * @param user User 对象
     * @param address Address 对象
     * @return UserDTO 对象
     */
    @Mappings(value = {
            @Mapping(source = "user.id", target = "userId"),
            @Mapping(source = "address.addressName", target = "address")
    })
    UserDTO toUserDTO03(User user, Address address);
}

测试代码:

java 复制代码
public class IssuesTest {

    @Test
    public void test03() {
        User user = new User(1001, "张三", 18);
        Address address = new Address("广东省");
        UserDTO userDTO = UserConvert.INSTANCE.toUserDTO03(user, address);
        System.out.println("userDTO = " + userDTO);
    }
}
相关推荐
一头生产的驴6 分钟前
java整合itext pdf实现自定义PDF文件格式导出
java·spring boot·pdf·itextpdf
YuTaoShao12 分钟前
【LeetCode 热题 100】73. 矩阵置零——(解法二)空间复杂度 O(1)
java·算法·leetcode·矩阵
zzywxc78716 分钟前
AI 正在深度重构软件开发的底层逻辑和全生命周期,从技术演进、流程重构和未来趋势三个维度进行系统性分析
java·大数据·开发语言·人工智能·spring
YuTaoShao2 小时前
【LeetCode 热题 100】56. 合并区间——排序+遍历
java·算法·leetcode·职场和发展
程序员张33 小时前
SpringBoot计时一次请求耗时
java·spring boot·后端
llwszx5 小时前
深入理解Java锁原理(一):偏向锁的设计原理与性能优化
java·spring··偏向锁
云泽野6 小时前
【Java|集合类】list遍历的6种方式
java·python·list
二进制person7 小时前
Java SE--方法的使用
java·开发语言·算法
小阳拱白菜8 小时前
java异常学习
java
程序员岳焱9 小时前
Java 与 MySQL 性能优化:Java 实现百万数据分批次插入的最佳实践
后端·mysql·性能优化