老鐵們是不是經(jīng)常為寫(xiě)一些實(shí)體轉(zhuǎn)換的原始代碼感到頭疼,尤其是實(shí)體字段特別多的時(shí)候。介紹一個(gè)開(kāi)源項(xiàng)目 mapstruct ,可以輕松優(yōu)雅的進(jìn)行轉(zhuǎn)換,簡(jiǎn)化你的代碼。當(dāng)然有的人喜歡寫(xiě)get set,或者用BeanUtils 進(jìn)行復(fù)制,代碼只是工具,本文只是提供一種思路。
先貼下官網(wǎng)地址吧:https://mapstruct.org/
廢話不多說(shuō),上代碼:
pom 配置:
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<org.mapstruct.version>1.4.1.Finalorg.mapstruct.version>
<org.projectlombok.version>1.18.12org.projectlombok.version>
properties>
<dependencies>
<dependency>
<groupId>org.mapstructgroupId>
<artifactId>mapstructartifactId>
<version>${org.mapstruct.version}version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${org.projectlombok.version}version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.mapstructgroupId>
<artifactId>mapstruct-processorartifactId>
<version>${org.mapstruct.version}version>
<scope>providedscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.8.1version>
<configuration>
<source>1.8source>
<target>1.8target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${org.projectlombok.version}version>
path>
<path>
<groupId>org.mapstructgroupId>
<artifactId>mapstruct-processorartifactId>
<version>${org.mapstruct.version}version>
path>
annotationProcessorPaths>
configuration>
plugin>
plugins>
build>
關(guān)于lombok和mapstruct的版本兼容問(wèn)題多說(shuō)幾句,maven插件要使用3.6.0版本以上、lombok使用1.16.16版本以上,另外編譯的lombok mapstruct的插件不要忘了加上。否則會(huì)出現(xiàn)下面的錯(cuò)誤:No property named "aaa" exists in source parameter(s). Did you mean "null"?
基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
- 項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 視頻教程:https://doc.iocoder.cn/video/
這種異常就是lombok編譯異常導(dǎo)致缺少get setter方法造成的。還有就是缺少構(gòu)造函數(shù)也會(huì)拋異常。
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
publicclassStudent{
privateStringname;
privateintage;
privateGenderEnumgender;
privateDoubleheight;
privateDatebirthday;
}
publicenumGenderEnum{
Male("1","男"),
Female("0","女");
privateStringcode;
privateStringname;
publicStringgetCode(){
returnthis.code;
}
publicStringgetName(){
returnthis.name;
}
GenderEnum(Stringcode,Stringname){
this.code=code;
this.name=name;
}
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
publicclassStudentVO{
privateStringname;
privateintage;
privateStringgender;
privateDoubleheight;
privateStringbirthday;
}
@Mapper
publicinterfaceStudentMapper{
StudentMapperINSTANCE=Mappers.getMapper(StudentMapper.class);
@Mapping(source="gender.name",target="gender")
@Mapping(source="birthday",target="birthday",dateFormat="yyyy-MM-ddHHss")
StudentVOstudent2StudentVO(Studentstudent);
}
實(shí)體類是開(kāi)發(fā)過(guò)程少不了的,就算是用工具生成肯定也是要有的,需要手寫(xiě)的部分就是這個(gè)Mapper的接口,編譯完成后會(huì)自動(dòng)生成相應(yīng)的實(shí)現(xiàn)類

然后就可以直接用mapper進(jìn)行實(shí)體的轉(zhuǎn)換了
publicclassTest{
publicstaticvoidmain(String[]args){
Studentstudent=Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(newDate()).build();
System.out.println(student);
//這行代碼便是實(shí)際要用的代碼
StudentVOstudentVO=StudentMapper.INSTANCE.student2StudentVO(student);
System.out.println(studentVO);
}
}

mapper可以進(jìn)行字段映射,改變字段類型,指定格式化的方式,包括一些日期的默認(rèn)處理。
可以手動(dòng)指定格式化的方法:
@Mapper
publicinterfaceStudentMapper{
StudentMapperINSTANCE=Mappers.getMapper(StudentMapper.class);
@Mapping(source="gender",target="gender")
@Mapping(source="birthday",target="birthday",dateFormat="yyyy-MM-ddHHss")
StudentVOstudent2StudentVO(Studentstudent);
defaultStringgetGenderName(GenderEnumgender){
returngender.getName();
}
}
上面只是最簡(jiǎn)單的實(shí)體映射處理,下面介紹一些高級(jí)用法
1、List 轉(zhuǎn)換
屬性映射基于上面的mapping配置
@Mapper
publicinterfaceStudentMapper{
StudentMapperINSTANCE=Mappers.getMapper(StudentMapper.class);
@Mapping(source="gender.name",target="gender")
@Mapping(source="birthday",target="birthday",dateFormat="yyyy-MM-ddHHss")
StudentVOstudent2StudentVO(Studentstudent);
Liststudents2StudentVOs(ListstudentList) ;
}
publicstaticvoidmain(String[]args){
Studentstudent=Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(newDate()).build();
Listlist=newArrayList<>();
list.add(student);
Listresult=StudentMapper.INSTANCE.students2StudentVOs(list);
System.out.println(result);
}

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
2、多對(duì)象轉(zhuǎn)換到一個(gè)對(duì)象
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
publicclassStudent{
privateStringname;
privateintage;
privateGenderEnumgender;
privateDoubleheight;
privateDatebirthday;
}
@Data
@AllArgsConstructor
@Builder
@NoArgsConstructor
publicclassCourse{
privateStringcourseName;
privateintsortNo;
privatelongid;
}
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
publicclassStudentVO{
privateStringname;
privateintage;
privateStringgender;
privateDoubleheight;
privateStringbirthday;
privateStringcourse;
}
@Mapper
publicinterfaceStudentMapper{
StudentMapperINSTANCE=Mappers.getMapper(StudentMapper.class);
@Mapping(source="student.gender.name",target="gender")
@Mapping(source="student.birthday",target="birthday",dateFormat="yyyy-MM-ddHHss")
@Mapping(source="course.courseName",target="course")
StudentVOstudentAndCourse2StudentVO(Studentstudent,Coursecourse);
}
publicclassTest{
publicstaticvoidmain(String[]args){
Studentstudent=Student.builder().name("小明").age(6).gender(GenderEnum.Male).height(121.1).birthday(newDate()).build();
Coursecourse=Course.builder().id(1L).courseName("語(yǔ)文").build();
StudentVOstudentVO=StudentMapper.INSTANCE.studentAndCourse2StudentVO(student,course);
System.out.println(studentVO);
}
}

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
- 項(xiàng)目地址:https://gitee.com/zhijiantianya/yudao-cloud
- 視頻教程:https://doc.iocoder.cn/video/
3、默認(rèn)值
@Mapper
publicinterfaceStudentMapper{
StudentMapperINSTANCE=Mappers.getMapper(StudentMapper.class);
@Mapping(source="student.gender.name",target="gender")
@Mapping(source="student.birthday",target="birthday",dateFormat="yyyy-MM-ddHHss")
@Mapping(source="course.courseName",target="course")
@Mapping(target="name",source="student.name",defaultValue="張三")
StudentVOstudentAndCourse2StudentVO(Studentstudent,Coursecourse);
}

-
spring
+關(guān)注
關(guān)注
0文章
340瀏覽量
14978 -
開(kāi)源項(xiàng)目
+關(guān)注
關(guān)注
0文章
38瀏覽量
7442
原文標(biāo)題:別再用 BeanUtils 了,這款 PO VO DTO 轉(zhuǎn)換神器不香么?
文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
THS4509運(yùn)放給+5V單電源供電,請(qǐng)問(wèn)輸出電壓Vo+ - Vo-最大能輸出多少V?
聲音有PO-PO雜聲?
厲害了word哥,這款手機(jī)無(wú)線充電產(chǎn)品牛掰了,你們?cè)趺纯窗。?/a>
請(qǐng)問(wèn)有人熟悉MSK4351這款IPM智能功率芯片么?這款芯片的外圍電路怎么搭建?有做過(guò)的么?
iOS版餓了么使用的開(kāi)源項(xiàng)目
體驗(yàn)未來(lái)餓了么無(wú)人機(jī)配送外賣服務(wù)
TCL么么噠3N拆解 手機(jī)內(nèi)部做工如何
蘋(píng)果iPhone 13系列真的那么香嗎?
PO VO DTO轉(zhuǎn)換神器的思路
MapStruct是用來(lái)做什么的
如何分清PO、VO、DAO、BO、DTO、POJO?
PO、VO、DAO、BO、DTO、POJO應(yīng)該怎么分層
深入淺出聊PLC技術(shù),無(wú)線智能家居瞬間「不香了」?

別再用offset和limit分頁(yè)了,OFFSET和LIMIT有什么問(wèn)題?

評(píng)論