遇到MapStruct后,再也不手写PO,DTO,VO对象之间的转换了
點擊上方?好好學java?,選擇?星標?公眾號
重磅資訊、干貨,第一時間送達今日推薦:騰訊推出高性能 RPC 開發框架
個人原創100W+訪問量博客:點擊前往,查看更多
介紹
在工作中,我們經常要進行各種對象之間的轉換。
PO:persistent object 持久對象,對應數據庫中的一條記錄
VO:view object 表現層對象,最終返回給前端的對象
DTO:data transfer object數據傳輸對象,如dubbo服務之間傳輸的對象
如果這些對象的屬性名相同還好,可以用如下工具類賦值
Spring BeanUtils Cglib BeanCopier 避免使用Apache BeanUtils,性能較差
如果屬性名不同呢?如果是將多個PO對象合并成一個VO對象呢?好在有MapStruct神器,可以幫助我們快速轉換
在pom文件中加入如下依賴即可
<dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-jdk8</artifactId><version>1.2.0.CR1</version> </dependency><dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>1.2.0.CR1</version><scope>provided</scope> </dependency>對象互轉
@Data @Builder public?class?StudentPO?{private?Integer?id;private?String?name;private?Integer?age;private?String?className; }@Data public?class?StudentVO?{private?Integer?id;private?String?studentName;private?Integer?studentAge;private?String?schoolName; }
@Mapper public?interface?StudentMapper?{StudentMapper?INSTANCE?=?Mappers.getMapper(StudentMapper.class);@Mappings({@Mapping(source?=?"name",?target?=?"studentName"),@Mapping(source?=?"age",?target?=?"studentAge")})StudentVO?po2Vo(StudentPO?studentPO); }
新建一個Mapper接口,上面加上@Mapper注解
新建一個成員變量INSTANCE
用@Mapping注解指定映射關系,名字相同的就不用再指定了,會自動映射
測試效果如下,名字不同且沒有指定映射關系的會被設置為null
@Test public?void?studentPo2Vo()?{StudentPO?studentPO?=?StudentPO.builder().id(10).name("test").age(24).className("教室名").build();StudentVO?studentVO?=?StudentMapper.INSTANCE.po2Vo(studentPO);//?StudentVO(id=10,?studentName=test,?studentAge=24,?schoolName=null)System.out.println(studentVO); }List互轉
@Mapper public?interface?StudentMapper?{StudentMapper?INSTANCE?=?Mappers.getMapper(StudentMapper.class);@Mappings({@Mapping(source?=?"name",?target?=?"studentName"),@Mapping(source?=?"age",?target?=?"studentAge")})StudentVO?po2Vo(StudentPO?studentPO);List<StudentVO>?poList2VoList(List<StudentPO>?studentPO); }List類型互轉的映射規則會用單個對象的映射規則,看測試效果
@Test public?void?poList2VoList()?{List<StudentPO>?studentPOList?=?new?ArrayList<>();for?(int?i?=?1;?i?<=?2;?i++)?{StudentPO?studentPO?=?StudentPO.builder().id(i).name(String.valueOf(i)).age(i).build();studentPOList.add(studentPO);}List<StudentVO>?studentVOList?=?StudentMapper.INSTANCE.poList2VoList(studentPOList);//?[StudentVO(id=1,?studentName=1,?studentAge=1,?schoolName=null),//?StudentVO(id=2,?studentName=2,?studentAge=2,?schoolName=null)]System.out.println(studentVOList); }多個對象映射一個對象
我們用SchoolPO和StudentPO來映射SchoolStudentVO
@Data @Builder public?class?SchoolPO?{private?String?name;private?String?location; }@Data @Builder public?class?StudentPO?{private?Integer?id;private?String?name;private?Integer?age;private?String?className; }
@Data public?class?SchoolStudentVO?{private?String?schoolName;private?String?studentName; }
@Mapper public?interface?StudentMapper?{@Mappings({@Mapping(source?=?"schoolPO.name",?target?=?"schoolName"),@Mapping(source?=?"studentPO.name",?target?=?"studentName")})SchoolStudentVO?mergeVo(SchoolPO?schoolPO,?StudentPO?studentPO); }
測試例子如下
@Test public?void?mergeVo()?{SchoolPO?schoolPO?=?SchoolPO.builder().name("學校名字").build();StudentPO?studentPO?=?StudentPO.builder().name("學生名字").build();SchoolStudentVO?schoolStudentVO?=?StudentMapper.INSTANCE.mergeVo(schoolPO,?studentPO);//?SchoolStudentVO(schoolName=學校名字,?studentName=學生名字)System.out.println(schoolStudentVO); }當然還有其他的騷操作,這里就簡單介紹一些比較實用的技巧,有興趣的可以看官方的example
https://github.com/mapstruct/mapstruct-examples
實現原理
MapStruct幫你對接口生成了一個實現類,下面就是生成的實現類,從class文件夾中可以看到
public?class?StudentMapperImpl?implements?StudentMapper?{public?StudentMapperImpl()?{}public?StudentVO?po2Vo(StudentPO?studentPO)?{if?(studentPO?==?null)?{return?null;}?else?{StudentVO?studentVO?=?new?StudentVO();studentVO.setStudentAge(studentPO.getAge());studentVO.setStudentName(studentPO.getName());studentVO.setId(studentPO.getId());return?studentVO;}}public?List<StudentVO>?poList2VoList(List<StudentPO>?studentPO)?{if?(studentPO?==?null)?{return?null;}?else?{List<StudentVO>?list?=?new?ArrayList(studentPO.size());Iterator?var3?=?studentPO.iterator();while(var3.hasNext())?{StudentPO?studentPO1?=?(StudentPO)var3.next();list.add(this.po2Vo(studentPO1));}return?list;}}public?SchoolStudentVO?mergeVo(SchoolPO?schoolPO,?StudentPO?studentPO)?{if?(schoolPO?==?null?&&?studentPO?==?null)?{return?null;}?else?{SchoolStudentVO?schoolStudentVO?=?new?SchoolStudentVO();if?(schoolPO?!=?null)?{schoolStudentVO.setSchoolName(schoolPO.getName());}if?(studentPO?!=?null)?{schoolStudentVO.setStudentName(studentPO.getName());}return?schoolStudentVO;}} }最后,再附上我歷時三個月總結的?Java 面試 + Java 后端技術學習指南,筆者這幾年及春招的總結,github 1.4k star,拿去不謝!下載方式1.?首先掃描下方二維碼 2.?后臺回復「Java面試」即可獲取
總結
以上是生活随笔為你收集整理的遇到MapStruct后,再也不手写PO,DTO,VO对象之间的转换了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你的Redis为什么变慢了?
- 下一篇: NIO这样理解才够深入!