這四種對象屬性拷貝方式,你都知道嗎?(推薦第四種)
一、MapStruct
1.1、 簡介:
MapStruct 是一個自動生成 bean 映射類的代碼生成器。MapStruct 還能夠在不同的數(shù)據類型之間進行轉換。
1.2、所需依賴
- mapstruct-jdk8
包含所需的注釋,例如@Mapping。
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.3.0.Final</version>
</dependency>
- mapstruct-processor
在編譯,生成映射器實現(xiàn)的注釋處理器。
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.3.0.Final</version>
<scope>provided</scope>
</dependency>
1.3、如何使用?
您所要做的就是定義一個mapper接口,該接口聲明任何所需的映射方法。在編譯期間,MapStruct將生成此接口的實現(xiàn)。此實現(xiàn)使用普通的Java方法調用來在源對象和目標對象之間進行映射。
- 創(chuàng)建Mapper
利用@Mapper注解標注該接口/抽象類是被MapStruct自動映射的,只有存在該注解才會將內部的接口方法自動實現(xiàn)。
- 獲取Mapper
MapStruct為我們提供了多種的獲取Mapper的方式,習慣用默認配置:采用Mappers通過動態(tài)工廠內部反射機制完成Mapper實現(xiàn)類的獲取。
UserConvertUtils INSTANCE = Mappers.getMapper(UserConvertUtils.class);
完整的一個轉換器demo:
@Mapper
public interface UserConvertUtils {
UserConvertUtils INSTANCE = Mappers.getMapper(UserConvertUtils.class);
/**
* 普通的映射
*
* @param userDO UserDO數(shù)據持久層類
* @return 數(shù)據傳輸類
*/
UserDTO doToDTO(UserDO userDO);
/**
* 類型轉換的映射
*
* @param userDO UserDO數(shù)據持久層類
* @return 數(shù)據傳輸類
*/
@Mappings({
@Mapping(target = "gmtBroth", source = "gmtBroth", dateFormat = "yyyy-MM-dd HH:mm:ss"),
@Mapping(target = "balances", source = "balance"),
})
UserDTO doToDtoWithConvert(UserDO userDO);
}
- 測試
/**
* 一般拷貝
*/
@Test
public void normalCopy() {
// 模擬查詢出數(shù)據
UserDO userDO = DataUtil.createData();
log.info("拷貝前:userDO:{}", userDO);
UserDTO userDTO = UserConvertUtils.INSTANCE.doToDTO(userDO);
log.info("拷貝后:userDTO:{}", userDTO);
}
/**
* 包含類型轉換的拷貝
*/
@Test
public void doToDtoWithConvert() {
// 模擬查詢出數(shù)據
UserDO userDO = DataUtil.createData();
log.info("拷貝前:userDO:{}", userDO);
UserDTO userDTO = UserConvertUtils.INSTANCE.doToDtoWithConvert(userDO);
log.info("拷貝后:userDTO:{}", userDTO);
}
- 打印映射結果
一般拷貝:
...拷貝前:userDO:UserDO(id=1, userName=Van, gmtBroth=2020-04-21T21:38:39.376, balance=100)
...拷貝后:userDTO:UserDTO(id=1, userName=Van, gmtBroth=2020-04-21T21:38:39.376, balances=null)
包含類型轉換的拷貝:
...拷貝前:userDO:UserDO(id=1, userName=Van, gmtBroth=2020-04-21T21:05:19.282, balance=100)
...拷貝后:userDTO:UserDTO(id=1, userName=Van, gmtBroth=2020-04-21 21:05:19, balances=100)
通過打印結果可以發(fā)現(xiàn):相較于前者,包含類型轉換的拷貝可以自定義轉換屬性和時間格式等。
1.4、MapStruct 注解的關鍵詞
- @Mapper:只有在接口加上這個注解, MapStruct 才會去實現(xiàn)該接口;
- @Mappings:配置多個@Mapping;
- @Mapping:屬性映射,若源對象屬性與目標對象名字一致,會自動映射對應屬性:
- source:源屬性;
- target:目標屬性;
- dateFormat:字符串與日期之間相互轉換;
- ignore:忽略這個,某個屬性不想映射,可以加個 ignore=true;
1.5、多對一
與手工編寫映射代碼相比,MapStruct通過生成繁瑣且易于編寫的代碼來節(jié)省時間。遵循約定優(yōu)于配置方法,MapStruct使用合理的默認值,但在配置或實現(xiàn)特殊行為時會采取措施。
與動態(tài)映射框架相比,MapStruct具有以下優(yōu)勢:
- 通過使用普通方法調用而不是反射來快速執(zhí)行
- 編譯時類型安全:只能映射相互映射的對象和屬性,不會將訂單實體意外映射到客戶DTO等。
- 在構建時清除錯誤報告,如果映射不完整(并非所有目標屬性都已映射)映射不正確(找不到合適的映射方法或類型轉換)