mapstruct是用来快速处理entity对象的属性复制的,话不多说,开整。
1.引入mapstruct依赖
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.1.Final</version>
</dependency>
2.编写UserDTO和UserVO实体
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO {
private Integer id;
private String name;
private Integer age;
private String address;
private Character gender;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserVO {
private Integer id;
private String name;
private Integer age;
private String address;
}
可看出,userDTO比userVO多个gender属性,而其余属性类型与字段名均相同。
3.写一个快速生成对象的方法
如下所示
public class Entity {
public static UserDTO getUserDTO(){
UserDTO userDTO = new UserDTO(1,"张三",28,"安徽省合肥市",'男');
return userDTO;
}
public static UserVO getUserVO(){
UserVO userVO = new UserVO(2,"李四",33,"浙江省杭州市");
return userVO;
}
}
4.1测试多属性对象向少属性对象复制(属性映射规则全写)
(1)编写mapper接口,如下
@Mapper
public interface UserMapper {
/**
* 获取该类自动生成的实现类的实例
* 接口中的属性都是 public static final 的 方法都是public abstract的
*/
UserMapper INSTANCES = Mappers.getMapper(UserMapper.class);
/**
* 这个方法就是用于实现对象属性复制的方法
*
* @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性 *
* @param userDTO 这个参数就是源对象,也就是需要被复制的对象
* @return 返回的是目标对象,就是最终的结果对象
*/
@Mappings({
@Mapping(source = "id",target = "id"),
@Mapping(source = "name",target = "name"),
@Mapping(source = "age",target = "age"),
@Mapping(source = "address",target = "address")
})
UserVO userDTOToUserVO(UserDTO userDTO);
}
其中注意@Mapper是org.mapstruct.Mapper包下的。
(2)接下来测试实体类字段多的一方复制到字段少的一方
@Test
public void $1() {
UserDTO userDTO = Entity.getUserDTO();
System.out.println(userDTO);
UserVO userVO = UserMapper.INSTANCES.userDTOToUserVO(userDTO);
System.out.println(userVO);
}
结果如下,可知多字段向少字段复制,多出的字段因没写@Mapping匹配规则而过滤掉
4.2测试多属性对象向少属性对象复制(属性映射规则不写)
(1)注释掉一个mapping
@Mappings({
@Mapping(source = "id",target = "id"),
@Mapping(source = "name",target = "name"),
//@Mapping(source = "age",target = "age"),
@Mapping(source = "address",target = "address")
})
UserVO userDTOToUserVO(UserDTO userDTO);
(2)测试结果如下,可知字段完全一样时可不写mapping
4.3测试少属性对象向多属性对象复制(属性映射规则全写)
(1)编写mapper
@Mappings({
@Mapping(source = "id",target = "id"),
@Mapping(source = "name",target = "name"),
@Mapping(source = "age",target = "age"),
@Mapping(source = "address",target = "address")
})
UserDTO userVOToUserDTO(UserVO userVO);
(2)测试
@Test
public void $3() {
UserVO userVO = Entity.getUserVO();
System.out.println(userVO);
UserDTO userDTO = UserMapper.INSTANCES.userVOToUserDTO(userVO);
System.out.println(userDTO);
}
结果如下
4.4测试少属性对象向多属性对象复制(属性映射规则不写)
(1)注释掉一个mapping
@Mappings({
@Mapping(source = "id",target = "id"),
//@Mapping(source = "name",target = "name"),
@Mapping(source = "age",target = "age"),
@Mapping(source = "address",target = "address")
})
UserDTO userVOToUserDTO(UserVO userVO);
(2)测试,结果如下,可知字段完全一样时可不写mapping
4.5测试多属性向少属性对象复制,且字段类型不同
(1)我们将UserDTO的age改为String类型
(2)编写mapper
@Mapping(source = "age",target = "age")
UserVO userDTOToUserVO(UserDTO userDTO);
结果如下
但如果我们UserDTO的age不是数字,转为UserVO则会报错
4.6测试对象一个对象属性向另一个String属性复制
(1)将UserDTO的address属性类型改为自定义的Address对象
public class Address {
private String address;
}
public class UserDTO {
private Integer id;
private String name;
private String age;
private Address userAddress;
private Character gender;
}
(2)编写mapper
@Mapping(source = "userAddress.address",target = "address")
UserVO userDTOToUserVO(UserDTO userDTO);
测试结果如下
5.异常总结
(1)Caused by: java.lang.RuntimeException: java.lang.ClassNotFoundException: Cannot find implementation for com.sanning.exercise2022maven.user.dao.mapper.UserMapper
该原因是mapper的实现类未生成
解决方案:加入以下依赖
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.1.Final</version>
</dependency>
(2)UserVO does not have an accessible constructor.
该原因是使用lombok版本与mapstruct不适应
解决方案:将lombok升级到1.18以上即可