别再用 BeanUtils 了,这款 PO VO DTO 转换神器不香么?

x33g5p2x  于2021-11-28 转载在 其他  
字(6.8k)|赞(0)|评价(0)|浏览(384)

老铁们是不是经常为写一些实体转换的原始代码感到头疼,尤其是实体字段特别多的时候。介绍一个开源项目 mapstruct ,可以轻松优雅的进行转换,简化你的代码。

当然有的人喜欢写get set,或者用BeanUtils 进行复制,代码只是工具,本文只是提供一种思路。

先贴下官网地址吧:https://mapstruct.org/

废话不多说,上代码:

pom 配置:

  1. <properties>
  2.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  3.         <maven.compiler.source>1.8</maven.compiler.source>
  4.         <maven.compiler.target>1.8</maven.compiler.target>
  5.         <org.mapstruct.version>1.4.1.Final</org.mapstruct.version>
  6.         <org.projectlombok.version>1.18.12</org.projectlombok.version>
  7. </properties>
  8. <dependencies>
  9.         <dependency>
  10.             <groupId>org.mapstruct</groupId>
  11.             <artifactId>mapstruct</artifactId>
  12.             <version>${org.mapstruct.version}</version>
  13.         </dependency>
  14.         <!-- lombok dependencies should not end up on classpath -->
  15.         <dependency>
  16.             <groupId>org.projectlombok</groupId>
  17.             <artifactId>lombok</artifactId>
  18.             <version>${org.projectlombok.version}</version>
  19.             <scope>provided</scope>
  20.         </dependency>
  21.         <!-- idea 2018.1.1 之前的版本需要添加下面的配置,后期的版本就不需要了,可以注释掉, 我自己用的2019.3 -->
  22.      <dependency>
  23.             <groupId>org.mapstruct</groupId>
  24.             <artifactId>mapstruct-processor</artifactId>
  25.             <version>${org.mapstruct.version}</version>
  26.             <scope>provided</scope>
  27.         </dependency>
  28. </dependencies>
  29. <build>
  30.         <plugins>
  31.             <plugin>
  32.                 <groupId>org.apache.maven.plugins</groupId>
  33.                 <artifactId>maven-compiler-plugin</artifactId>
  34.                 <version>3.8.1</version>
  35.                 <configuration>
  36.                     <source>1.8</source>
  37.                     <target>1.8</target>
  38.                     <annotationProcessorPaths>
  39.                         <path>
  40.                             <groupId>org.projectlombok</groupId>
  41.                             <artifactId>lombok</artifactId>
  42.                             <version>${org.projectlombok.version}</version>
  43.                         </path>
  44.                         <path>
  45.                             <groupId>org.mapstruct</groupId>
  46.                             <artifactId>mapstruct-processor</artifactId>
  47.                             <version>${org.mapstruct.version}</version>
  48.                         </path>
  49.                     </annotationProcessorPaths>
  50.                 </configuration>
  51.             </plugin>
  52.         </plugins>
  53.     </build>

关于lombok和mapstruct的版本兼容问题多说几句,maven插件要使用3.6.0版本以上、lombok使用1.16.16版本以上,另外编译的lombok mapstruct的插件不要忘了加上。否则会出现下面的错误:No property named "aaa" exists in source parameter(s). Did you mean "null"?

这种异常就是lombok编译异常导致缺少get setter方法造成的。还有就是缺少构造函数也会抛异常。学习资料:Java进阶视频资源

  1. @Data
  2. @Builder
  3. @AllArgsConstructor
  4. @NoArgsConstructor
  5. public class Student {
  6.     private String name;
  7.     private int age;
  8.     private GenderEnum gender;
  9.     private Double height;
  10.     private Date birthday;
  11. }
  12. public enum GenderEnum {
  13.     Male("1", "男"),
  14.     Female("0", "女");
  15.     private String code;
  16.     private String name;
  17.     public String getCode() {
  18.         return this.code;
  19.     }
  20.     public String getName() {
  21.         return this.name;
  22.     }
  23.     GenderEnum(String code, String name) {
  24.         this.code = code;
  25.         this.name = name;
  26.     }
  27. }
  28. @Data
  29. @Builder
  30. @AllArgsConstructor
  31. @NoArgsConstructor
  32. public class StudentVO {
  33.     private String name;
  34.     private int age;
  35.     private String gender;
  36.     private Double height;
  37.     private String birthday;
  38. }
  39. @Mapper
  40. public interface StudentMapper {
  41.     StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
  42.     @Mapping(source = "gender.name", target = "gender")
  43.     @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
  44.     StudentVO student2StudentVO(Student student);
  45. }

实体类是开发过程少不了的,就算是用工具生成肯定也是要有的,需要手写的部分就是这个Mapper的接口,编译完成后会自动生成相应的实现类

然后就可以直接用mapper进行实体的转换了

  1. public class Test {
  2.     public static void main(String[] args) {
  3.         Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();
  4.         System.out.println(student);
  5.         //这行代码便是实际要用的代码
  6.         StudentVO studentVO = StudentMapper.INSTANCE.student2StudentVO(student);
  7.         System.out.println(studentVO);
  8.     }
  9. }

mapper可以进行字段映射,改变字段类型,指定格式化的方式,包括一些日期的默认处理。

可以手动指定格式化的方法:

  1. @Mapper
  2. public interface StudentMapper {
  3.     StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
  4.     @Mapping(source = "gender", target = "gender")
  5.     @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
  6.     StudentVO student2StudentVO(Student student);
  7.     default String getGenderName(GenderEnum gender) {
  8.         return gender.getName();
  9.     }
  10. }

上面只是最简单的实体映射处理,下面介绍一些高级用法

1.List 转换

属性映射基于上面的mapping配置

  1. @Mapper
  2. public interface StudentMapper {
  3.     StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
  4.     @Mapping(source = "gender.name", target = "gender")
  5.     @Mapping(source = "birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
  6.     StudentVO student2StudentVO(Student student);
  7.     List<StudentVO> students2StudentVOs(List<Student> studentList);
  8. }
  9. public static void main(String[] args) {
  10.     Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();
  11.     List<Student> list = new ArrayList<>();
  12.     list.add(student);
  13.     List<StudentVO> result = StudentMapper.INSTANCE.students2StudentVOs(list);
  14.     System.out.println(result);
  15. }

2.多对象转换到一个对象

  1. @Data
  2. @Builder
  3. @AllArgsConstructor
  4. @NoArgsConstructor
  5. public class Student {
  6.     private String name;
  7.     private int age;
  8.     private GenderEnum gender;
  9.     private Double height;
  10.     private Date birthday;
  11. }
  12. @Data
  13. @AllArgsConstructor
  14. @Builder
  15. @NoArgsConstructor
  16. public class Course {
  17.     private String courseName;
  18.     private int sortNo;
  19.     private long id;
  20. }
  21. @Data
  22. @Builder
  23. @AllArgsConstructor
  24. @NoArgsConstructor
  25. public class StudentVO {
  26.     private String name;
  27.     private int age;
  28.     private String gender;
  29.     private Double height;
  30.     private String birthday;
  31.     private String course;
  32. }
  33. @Mapper
  34. public interface StudentMapper {
  35.     StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
  36.     @Mapping(source = "student.gender.name", target = "gender")
  37.     @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
  38.     @Mapping(source = "course.courseName", target = "course")
  39.     StudentVO studentAndCourse2StudentVO(Student student, Course course);
  40. }
  41. public class Test {
  42.     public static void main(String[] args) {
  43.         Student student = Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(new Date()).build();
  44.         Course course = Course.builder().id(1L).courseName("语文").build();
  45.         StudentVO studentVO = StudentMapper.INSTANCE.studentAndCourse2StudentVO(student, course);
  46.         System.out.println(studentVO);
  47.     }
  48. }

3.默认值

  1. @Mapper
  2. public interface StudentMapper {
  3.     StudentMapper INSTANCE = Mappers.getMapper(StudentMapper.class);
  4.     @Mapping(source = "student.gender.name", target = "gender")
  5.     @Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss")
  6.     @Mapping(source = "course.courseName", target = "course")
  7.     @Mapping(target = "name", source = "student.name", defaultValue = "张三")
  8.     StudentVO studentAndCourse2StudentVO(Student student, Course course);
  9. }

(完)

  1. 【推荐阅读】
  2. 实战!基于Security+JWT的单点登陆开发及原理解析
  3. 撸了个DDD项目,爽!
  4. 程序员玩‘附近的人’,妹子还没泡,先学会了个专业技能!

好文章!点个在看!

相关文章