Mapstruct?@Mapper?@Mapping?使用小結
作用
用于各個對象實體間的相互轉換,例如數據庫底層實體 轉為頁面對象,Model 轉為 DTO(data transfer object 數據轉換實體), DTO 轉為其他中間對象, VO 等等,相關轉換代碼為編譯時自動產生的新文件和代碼。
兩個對象之間相同屬性名的會被自動轉換,指定特殊情況時需要通過注解在抽象方法上說明不同屬性之間的轉換。
轉換方法一般均為抽象方法,所以這一類文件一般使用 接口 類,或者抽象類均可,官方的介紹一般均使用了接口類文件來完成。如果感興趣可以到官網看看
Maven 依賴
官方給與的示例配置,建議使用官方推薦的版本
... <properties> <org.mapstruct.version>1.5.2.Final</org.mapstruct.version> </properties> ... <dependencies> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>${org.mapstruct.version}</version> </dependency> </dependencies> ... <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${org.mapstruct.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build> ...
在本地經過一些實驗后,發(fā)現這樣也可以
<dependencies> ........ <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.4.2.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.2.0.Final</version> </dependency> </dependencies>
這里我 IDEA 版本為 2020.1
特別注意,mapstruct 以及 mapstruct-processor 不論哪種形式兩個都需要同時存在,mapstruct 提供了注解等,mapstruct-processor 會在編譯時將相關接口文件的實現類生成出來,最終完成想要的映射實現。
若與 lombok 連用
如果同時使用了另一個 lombok 代碼生成相關的依賴,那么需要注意lombok maven 依賴版本需要在 1.16.16 以上,否則可能會出現
**No property named “XXX“ exists in source parameter(s). Did you mean “null“?**之類的錯誤
使用示例
1.基本使用
定義兩個類如下:
這里使用了lombok 實際上僅僅是簡化了 get set 以及構造方法之類的。
如果需要,可以看看另一篇關于 lombok 的介紹@Data 注解使用 lombok插件學習總結
實體一DTO:
package org.aurora.lombok; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; @Data @AllArgsConstructor @NoArgsConstructor @Builder public class PersionDTO { private Long pId; private String name; private Integer age; private String sex; private String address; private Float height; private Float weight; private Date birthDay; private String birthLocation; private Boolean married; private Boolean hasParents; private Boolean hasChildren; private String describe; }
其中
@Data 編譯時幫助實現了 get set 方法
@AllArgsConstructor 全參構造函數
@NoArgsConstructor 無參構造函數
@Builder 允許使用 builder 方式構造對象,其實和構造函數差不多
另一個實體 VO:
package org.aurora.lombok; import lombok.Data; import lombok.ToString; @Data @ToString public class PersonVO { private Long pId; private String name; private Integer age; private String sex; private String des; private String birth; private String choice; }
開始加入 MapStruct 的轉換相關的,注意這里我定義的是抽象類,實際上使用接口類也可以先看看正常的接口類
package org.aurora.mapstruct; import org.aurora.lombok.PersionDTO; import org.aurora.lombok.PersonVO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; @Mapper public interface MyMapper { MyMapper INSTANCE = Mappers.getMapper(MyMapper.class); @Mapping(source = "describe", target = "des") PersonVO transToViewObject(PersionDTO persionDTO); }
上面可以如下解釋
@Mapper 當前類認為是要執(zhí)行 MapStruct 相關操作的類
@Mapping 為指定某些特殊映射的注解,沒有指定的內容,當源對象與 目標對象擁有一樣的屬性時會自動轉換
INSTANCE 是為了在外面外面調用該方法, 接口中的屬性默認為靜態(tài)屬性所以可以直接調用到
@Mapping 中 source 為入參,源對象的屬性名, target 為目標對象的屬性 source 和 target 沒有順序之分,按自己的來即可
生成代碼如下,注意這些代碼是直接生成到 classes 里面的
package org.aurora.mapstruct; import javax.annotation.Generated; import org.aurora.lombok.PersionDTO; import org.aurora.lombok.PersonVO; @Generated( value = "org.mapstruct.ap.MappingProcessor", date = "2022-08-11T16:24:31+0800", comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_211 (Oracle Corporation)" ) public class MyMapperImpl implements MyMapper { @Override public PersonVO transToViewObject(PersionDTO persionDTO) { if ( persionDTO == null ) { return null; } PersonVO personVO = new PersonVO(); personVO.setDes( persionDTO.getDescribe() ); personVO.setPId( persionDTO.getPId() ); personVO.setName( persionDTO.getName() ); personVO.setAge( persionDTO.getAge() ); personVO.setSex( persionDTO.getSex() ); return personVO; } }
在Main 中測試如下:
public static void main(String[] args){ // 其實就是一個構造方法??梢钥醋鬟B續(xù)的set 屬性。 PersionDTO persionDTO = PersionDTO.builder().pId(1515435488753L).name("小天").age(-2).sex("male").birthDay(new Date()).address("甘雨胡同十六號").height(18f).weight(4f) .birthLocation("chinese").describe("嗷嗷嗷").married(false).hasChildren(false).hasParents(true).build(); // 轉化 PersonVO personVO = MyMapper.INSTANCE.transToViewObject(persionDTO); System.out.println(personVO.toString()); }
結果如下
PersonVO(pId=1515435488753, name=小天, age=-2, sex=male, des=嗷嗷嗷, birth=null, choice=null)
可以看出來,當兩個實體中的參數中存在一致的屬性時會被自動轉換,屬性名對不上如果 @Mapping 沒有指定的處理方式,則不會處理,實際上這一條已經適用于大多數場景。
接下來看下使用抽象類的方式,結果大同小異
轉換類如下定義:
package org.aurora.mapstruct; import org.aurora.lombok.PersionDTO; import org.aurora.lombok.PersonVO; import org.mapstruct.AfterMapping; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; import org.mapstruct.factory.Mappers; import java.text.SimpleDateFormat; import java.util.Date; @Mapper public abstract class AbstractPersonConverter { public static final AbstractPersonConverter INSTANCE = Mappers.getMapper(AbstractPersonConverter.class); /** * persionDTO 轉到 PersonVO * @param persionDTO * @return */ @Mapping(source = "describe", target = "des") public abstract PersonVO transToViewObject(PersionDTO persionDTO); /** * persionDTO 轉到 personVO的后置轉換處理 * @param personVO * @param persionDTO */ @AfterMapping void changeDateIntoStr(@MappingTarget PersonVO personVO, PersionDTO persionDTO ){ Date birthDay = persionDTO.getBirthDay(); if (birthDay != null){ personVO.setBirth(transDate(birthDay)); } } /** * 日期轉換 * @param date * @return */ String transDate(Date date){ if (date == null){ return null; } SimpleDateFormat simpleDateFormat = new SimpleDateFormat("y-M-d"); String format = simpleDateFormat.format(date); return format; } }
生成代碼如下:
package org.aurora.mapstruct; import javax.annotation.Generated; import org.aurora.lombok.PersionDTO; import org.aurora.lombok.PersonVO; @Generated( value = "org.mapstruct.ap.MappingProcessor", date = "2022-08-11T15:11:27+0800", comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_211 (Oracle Corporation)" ) public class AbstractPersonConverterImpl extends AbstractPersonConverter { @Override public PersonVO transToViewObject(PersionDTO persionDTO) { if ( persionDTO == null ) { return null; } PersonVO personVO = new PersonVO(); personVO.setDes( persionDTO.getDescribe() ); personVO.setPId( persionDTO.getPId() ); personVO.setName( persionDTO.getName() ); personVO.setAge( persionDTO.getAge() ); personVO.setSex( persionDTO.getSex() ); changeDateIntoStr( personVO, persionDTO ); return personVO; } }
其中
2.@AfterMapping @BeforeMapping
為指定某類型換為某一類型指定的在一般Mapping 結束后附加的操作@MappingTarget PersonVO personVO 指定了最終轉換結果為 PersonVO 類的對象,personVO 以及 persionDTO 均為入參,在這里可以做一些自己的額外操作
實驗代碼:
public static void main(String[] args){ PersionDTO persionDTO = PersionDTO.builder().pId(1515435488753L).name("小天").age(-2).sex("male").birthDay(new Date()).address("甘雨胡同十六號").height(18f).weight(4f) .birthLocation("chinese").describe("嗷嗷嗷").married(false).hasChildren(false).hasParents(true).build(); PersonVO personVO = AbstractPersonConverter.INSTANCE.transToViewObject(persionDTO); System.out.println(personVO.toString()); }
最終結果:
PersonVO(pId=1515435488753, name=小天, age=-2, sex=male, des=嗷嗷嗷, birth=2022-8-11, choice=null)
可以看得出最終的 結果中對 birth 的特殊操作是成功進入了最終的結果,實際上這里的時間轉換可以通過 Mapstruct 的注解自帶功能完成。AfterMapping 中支持我們做更多特殊的業(yè)務操作,@BeforeMapping與 AfterMapping 相反 會在實際映射方法前執(zhí)行,但作用一致
3.多個入參轉為一個對象
上面的方法多添加一個抽象方法如下:
@Mapping(source = "persionDTO.describe", target = "des") @Mapping(source = "apee.ap", target = "choice") public abstract PersonVO transToViewObject(PersionDTO persionDTO, Apee apee);
生成的代碼如下:
@Override public PersonVO transToViewObject(PersionDTO persionDTO, Apee apee) { if ( persionDTO == null && apee == null ) { return null; } PersonVO personVO = new PersonVO(); if ( persionDTO != null ) { personVO.setDes( persionDTO.getDescribe() ); personVO.setPId( persionDTO.getPId() ); personVO.setName( persionDTO.getName() ); personVO.setAge( persionDTO.getAge() ); personVO.setSex( persionDTO.getSex() ); } if ( apee != null ) { personVO.setChoice( apee.getAp() ); } changeDateIntoStr( personVO, persionDTO ); return personVO; }
測試代碼:
public static void main(String[] args){ PersionDTO persionDTO = PersionDTO.builder().pId(1515435488753L).name("小天").age(-2).sex("male").birthDay(new Date()).address("甘雨胡同十六號").height(18f).weight(4f) .birthLocation("chinese").describe("嗷嗷嗷").married(false).hasChildren(false).hasParents(true).build(); Apee apee = new Apee(); apee.setAp("hahahahahaha"); PersonVO personVO = AbstractPersonConverter.INSTANCE.transToViewObject(persionDTO, apee); System.out.println(personVO.toString()); }
結果:
PersonVO(pId=1515435488753, name=小天, age=-2, sex=male, des=嗷嗷嗷, birth=2022-8-11, choice=hahahahahaha)
這里需要注意的是,當你的多個對象作為入參時,多個對象均含有同一個屬性時即當目標對象與另外多個入參都含有一個或多個相同屬性時,在mapping 也需要指定,否則不知道拿哪個屬性會拋出異常。
4.當源屬性沒有時指定默認值
在Mapping 中添加 default 屬性,給與默認值即可,例如:
@Mapping(source = "persionDTO.describe", target = "des") @Mapping(source = "apee.ap", target = "choice", defaultValue = "給個默認值") public abstract PersonVO transToViewObject(PersionDTO persionDTO, Apee apee);
生成的代碼
@Override public PersonVO transToViewObject(PersionDTO persionDTO, Apee apee) { if ( persionDTO == null && apee == null ) { return null; } PersonVO personVO = new PersonVO(); if ( persionDTO != null ) { personVO.setDes( persionDTO.getDescribe() ); personVO.setPId( persionDTO.getPId() ); personVO.setName( persionDTO.getName() ); personVO.setAge( persionDTO.getAge() ); personVO.setSex( persionDTO.getSex() ); } if ( apee != null ) { if ( apee.getAp() != null ) { personVO.setChoice( apee.getAp() ); } else { personVO.setChoice( "給個默認值" ); } } changeDateIntoStr( personVO, persionDTO ); return personVO; }
執(zhí)行測試代碼:
public static void main(String[] args){ PersionDTO persionDTO = PersionDTO.builder().pId(1515435488753L).name("小天").age(-2).sex("male").birthDay(new Date()).address("甘雨胡同十六號").height(18f).weight(4f) .birthLocation("chinese").describe("嗷嗷嗷").married(false).hasChildren(false).hasParents(true).build(); Apee apee = new Apee(); // apee.setAp("hahahahahaha"); PersonVO personVO = AbstractPersonConverter.INSTANCE.transToViewObject(persionDTO, apee); System.out.println(personVO.toString()); }
結果:
PersonVO(pId=1515435488753, name=小天, age=-2, sex=male, des=嗷嗷嗷, birth=2022-8-11, choice=給個默認值)
5.一般的類型以及日期轉換(dateFormat), 數字轉換(numberFormat)
之前的 Apee 定義如下
package org.aurora.lombok; import java.util.Date; public class Apee { private String ap; private String cp; private Date timeAA; private String strTime; public String getCp() { return cp; } public void setCp(String cp) { this.cp = cp; } public Date getTimeAA() { return timeAA; } public void setTimeAA(Date timeAA) { this.timeAA = timeAA; } public String getStrTime() { return strTime; } public void setStrTime(String strTime) { this.strTime = strTime; } public Apee() { } public Apee(String ap, String cp) { this.ap = ap; this.cp = cp; } public String getAp() { return ap; } public void setAp(String ap) { this.ap = ap; } @Override public String toString() { return "Apee{" + "ap='" + ap + '\'' + ", cp='" + cp + '\'' + ", timeAA=" + timeAA + ", strTime='" + strTime + '\'' + '}'; } }
抽象方法定義如下:
@Mapping(source = "persionDTO.birthDay", target = "strTime", dateFormat = "yyyy-MM-dd") @Mapping(source = "persionDTO.describe", target = "timeAA", dateFormat = "yyyy-MM-dd") @Mapping(source = "persionDTO.age", target = "ap") public abstract Apee transDateToApee(PersionDTO persionDTO);
生成代碼:
@Override public Apee transDateToApee(PersionDTO persionDTO) { if ( persionDTO == null ) { return null; } Apee apee = new Apee(); try { if ( persionDTO.getDescribe() != null ) { apee.setTimeAA( new SimpleDateFormat( "yyyy-MM-dd" ).parse( persionDTO.getDescribe() ) ); } } catch ( ParseException e ) { throw new RuntimeException( e ); } if ( persionDTO.getBirthDay() != null ) { apee.setStrTime( new SimpleDateFormat( "yyyy-MM-dd" ).format( persionDTO.getBirthDay() ) ); } if ( persionDTO.getAge() != null ) { apee.setAp( String.valueOf( persionDTO.getAge() ) ); } return apee; }
測試代碼:
public static void main(String[] args){ PersionDTO persionDTO = PersionDTO.builder().pId(1515435488753L).name("小天").age(-2).sex("male").birthDay(new Date()).address("甘雨胡同十六號").height(18f).weight(4f) .birthLocation("chinese").describe("2022-07-08").married(false).hasChildren(false).hasParents(true).build(); Apee personVO = AbstractPersonConverter.INSTANCE.transDateToApee(persionDTO); System.out.println(personVO.toString()); }
測試結果:
Apee{ap='-2', cp='null', timeAA=Fri Jul 08 00:00:00 CST 2022, strTime='2022-08-11'}
可以看的出當指定日期格式 dateFormat 時 不論是從 String 到 Date 還是 Date 到 String 還是一般的類型轉 String 等等都可以自動完成適應,而且我發(fā)現當我提供 日期轉換方法時它竟然自動引用了我的方法,當我刪除時,它使用了自己生成的代碼
在上方轉化代碼中我提供了
/** * 日期轉換 * @param date * @return */ String transDate(Date date){ if (date == null){ return null; } SimpleDateFormat simpleDateFormat = new SimpleDateFormat("y-M-d"); String format = simpleDateFormat.format(date); return format; }
結果生成的代碼如下:
@Override public Apee transDateToApee(PersionDTO persionDTO) { if ( persionDTO == null ) { return null; } Apee apee = new Apee(); try { if ( persionDTO.getDescribe() != null ) { apee.setTimeAA( new SimpleDateFormat( "yyyy-MM-dd" ).parse( persionDTO.getDescribe() ) ); } } catch ( ParseException e ) { throw new RuntimeException( e ); } apee.setStrTime( transDate( persionDTO.getBirthDay() ) ); if ( persionDTO.getAge() != null ) { apee.setAp( String.valueOf( persionDTO.getAge() ) ); } return apee; }
官方支持的基本類型自動轉換大致如下:
基本類型及其對應的包裝類之間:比如, int 和 Integer, float 和 Float, long 和 Long,boolean 和 Boolean 等
任意基本類型與任意包裝類之間:如 int 和 long, byte 和 Integer 等
所有基本類型及包裝類與String之間:如 boolean 和 String, Integer 和 String, float 和 String 等枚舉和String之間。
Java大數類型(java.math.BigInteger, java.math.BigDecimal) 和Java基本類型(包括其包裝類)與String之間
數字轉String numberFormat
即 數字類型轉String 指定格式下也是支持的
上面方法修改如下:
@Mapping(source = "persionDTO.birthDay", target = "strTime", dateFormat = "yyyy-MM-dd") @Mapping(source = "persionDTO.describe", target = "timeAA", dateFormat = "yyyy-MM-dd") @Mapping(source = "persionDTO.age", target = "ap", numberFormat = "#0.00歲") public abstract Apee transDateToApee(PersionDTO persionDTO);
生成的關鍵代碼:
if ( persionDTO.getAge() != null ) { apee.setAp( new DecimalFormat( "#0.00歲" ).format( persionDTO.getAge() ) ); }
實際測試輸出后:
Apee{ap='-2.00歲', cp='null', timeAA=Fri Jul 08 00:00:00 CST 2022, strTime='2022-8-12'}
6.Expression 表達式以及 Mappings
Expression 可以用來替代 source 中的一般屬性,允許直接寫入一般的 java 表達式,即自己提供source 的表達式,但目前支持 Java 一種語言。
Mappings 可以理解為一個 普通 Mapping 的父標簽,允許里面放多個 Mapping 使用 ,分割與直接寫 多個Mapping 沒什么區(qū)別,
Expression 與 Mappings 沒必要連用,這里只是為了同時介紹
示例如下:
@Mappings({ @Mapping(expression = "java( new java.util.Date() )", target = "timeAA"), @Mapping(source = "persionDTO.age", target = "ap") }) public abstract Apee transExpressionToApee(PersionDTO persionDTO);
生成的代碼如下:
@Override public Apee transExpressionToApee(PersionDTO persionDTO) { if ( persionDTO == null ) { return null; } Apee apee = new Apee(); if ( persionDTO.getAge() != null ) { apee.setAp( String.valueOf( persionDTO.getAge() ) ); } apee.setTimeAA( new java.util.Date() ); return apee; }
7.轉換時 不使用對象中的同名屬性 使用指定參數作為某一屬性的值
當我們兩個對象中的屬性一樣,但是并不想使用時可以如下類似定義此時 PersonVO PersionDTO均含有PId 但是我并不想使用對象中的值而是采用我傳入的值,則如下:
/** * 使用其他值 * @param persionDTO * @param id * @return */ @Mapping(source = "persionDTO.describe", target = "des") @Mapping(source = "id", target = "PId") public abstract PersonVO transToViewObject2(PersionDTO persionDTO, Long id);
注意如果有其他值需要特殊處理時 需要如上指定參數,否則可能編譯時出現錯誤
生成的代碼
@Override public PersonVO transToViewObject2(PersionDTO persionDTO, Long id) { if ( persionDTO == null && id == null ) { return null; } PersonVO personVO = new PersonVO(); if ( persionDTO != null ) { personVO.setDes( persionDTO.getDescribe() ); personVO.setName( persionDTO.getName() ); personVO.setAge( persionDTO.getAge() ); personVO.setSex( persionDTO.getSex() ); } if ( id != null ) { personVO.setPId( id ); } return personVO; }
8.其他類作為屬性時
與一般的引用類型一致,當兩個類中都含有某一個同類型的同名屬性時,即使是類也會自動映射,如果類型一致,但是名稱不一致,則指定名稱后依舊會自動映射上面的兩個類中添加同一類型的一個類如下:
轉換方法如下定義:
@Mapping(source = "describe", target = "des") @Mapping(source = "apee", target = "apee2") public abstract PersonVO transToViewObject(PersionDTO persionDTO);
生成代碼如下
@Override public PersonVO transToViewObject(PersionDTO persionDTO) { if ( persionDTO == null ) { return null; } PersonVO personVO = new PersonVO(); personVO.setApee2( persionDTO.getApee() ); personVO.setDes( persionDTO.getDescribe() ); personVO.setPId( persionDTO.getPId() ); personVO.setName( persionDTO.getName() ); personVO.setAge( persionDTO.getAge() ); personVO.setSex( persionDTO.getSex() ); return personVO; }
9.逆映射
即 一個文件內,兩個類之間互相轉換映射時其實只要寫好其中一個映射,另一個可以通過注解繼承原有映射配置,即原有的 target 與 source 會互換
@Mapping(source = "describe", target = "des") @Mapping(source = "apee", target = "apee2") public abstract PersonVO transToViewObject(PersionDTO persionDTO); @InheritInverseConfiguration public abstract PersionDTO transToViewObject(PersonVO personVO);
生成代碼:
@Override public PersonVO transToViewObject(PersionDTO persionDTO) { if ( persionDTO == null ) { return null; } PersonVO personVO = new PersonVO(); personVO.setApee2( persionDTO.getApee() ); personVO.setDes( persionDTO.getDescribe() ); personVO.setPId( persionDTO.getPId() ); personVO.setName( persionDTO.getName() ); personVO.setAge( persionDTO.getAge() ); personVO.setSex( persionDTO.getSex() ); return personVO; } @Override public PersionDTO transToViewObject(PersonVO personVO) { if ( personVO == null ) { return null; } PersionDTO persionDTO = new PersionDTO(); persionDTO.setApee( personVO.getApee2() ); persionDTO.setDescribe( personVO.getDes() ); persionDTO.setPId( personVO.getPId() ); persionDTO.setName( personVO.getName() ); persionDTO.setAge( personVO.getAge() ); persionDTO.setSex( personVO.getSex() ); return persionDTO; }
10.支持注入spring
在mapper 上添加注解 類似如下:
之后該類可通過 @Autowired 注入方式引入到文件中
11. 自定義映射 ,list, Map, 枚舉
以下四種映射案例參考了其他文章的代碼參考博客
自定義映射 @Named
// 自定義的映射方法:轉換boolen為String時,做一些判斷然后返回對應的值。 @Named("DoneFormater") public class DoneFormater { @Named("DoneFormater") public String toStr(Boolean isDone) { if (isDone) { return "已完成"; } else { return "未完成"; } } @Named("DoneDetailFormater") public String toDetail(Boolean isDone) { if (isDone) { return "該產品已完成"; } else { return "該產品未完成"; } } public Boolean toBoolean(String str) { if (str.equals("已完成")) { return true; } else { return false; } } } // 通過uses 來導入上面我們寫的 自定義映射方法 @Mapper( uses = {DoneFormater.class}) public interface ObjectQualiferMapper { ObjectQualiferMapper INSTANCE = Mappers.getMapper(ObjectQualiferMapper.class); // 當有多個方法 擁有一樣的參數和返回類型時,需要指定使用其中的哪一個,使用qualifiedByName指定 @Mapping(source = "isDone", target = "isDone", qualifiedByName = "DoneDetailFormater") ProductDTO toDto(Product product); }
List 映射
@Mapper(componentModel = "spring") public interface UserMapping { /** * Student 轉化為 User * @param Student * @return */ User studentToUser(Student student); // 當執(zhí)行 下面這個List的轉換時,會遍歷list: students, // 然后自動調用上面的Student轉User的轉換方法,來進行轉換 /** * Students 轉化為 Users * @param Students * @return */ List<user> studentsToUsers(List<student> students); }
map 映射
@Mapper public interface MapMapper { MapMapper INSTANCE = Mappers.getMapper(MapMapper.class); @MapMapping(valueDateFormat = "yyyy-MM-dd HH:mm:ss") Map<string, string=""> toDTO(Map<long, date=""> map); }
枚舉
public enum E1 { E1_1, E1_2, E1_3 } public enum E2 { E2_1, E2_2, E2_3 }
映射方法:使用@ValueMappings和@ValueMapping ,可以理解成是用if判斷枚舉值,然后返回對應結果
@Mapper public interface DataEnumMapper { DataEnumMapper INSTANCE = Mappers.getMapper(DataEnumMapper.class); @ValueMappings({ @ValueMapping(target = "E1_1", source = "E2_1"), @ValueMapping(target = "E1_2", source = "E2_2"), @ValueMapping(target = MappingConstants.NULL, source = "E2_3") //轉換成null }) E1 toDTO(E2 e2); }
Final. 其他問題
出現問題 Couldn’t retrieve @Mapper annotation
可能是 項目中使用了swagger,swagger里面也包含mapstruct,排除掉就好
<dependency> <groupid>io.springfox</groupid> <artifactid>springfox-swagger2</artifactid> <version>${swagger2.version}</version> <scope>compile</scope> <exclusions> <exclusion> <groupid>org.mapstruct</groupid> <artifactid>mapstruct</artifactid> </exclusion> </exclusions> </dependency>
也可能是 導入mapstruct項目時,同時使用了 mapstruct-jdk8 和 mapstruct-processor 但版本不一致,將版本號改為一樣即可
更多詳細說明參見官網說明文檔
https://mapstruct.org/documentation/stable/reference/html/#defining-mapper
到此這篇關于Mapstruct @Mapper @Mapping 使用介紹以及總結的文章就介紹到這了,更多相關Mapstruct @Mapper @Mapping 使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
MyBatis-Plus中AutoGenerator的使用案例
AutoGenerator是MyBatis-Plus的代碼生成器,通過?AutoGenerator?可以快速生成?Pojo、Mapper、?Mapper?XML、Service、Controller?等各個模塊的代碼,這篇文章主要介紹了MyBatis-Plus中AutoGenerator的詳細使用案例,需要的朋友可以參考下2023-05-05