简介
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>
        使用示例
这里通过创建 User 和 UserDTO 两个类进行进行相互转换
创建 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);
    }
}