每天堅持寫一篇原創文章。
使用過MapStruct之後,再也沒用過BeanCopy來複制物件了。確實是非常好用的工具庫。
MapStruct是一個程式碼生成器,簡化了不同的Java Bean之間對映的處理,所以對映指的就是從一個實體變化成一個實體。例如我們在實際開發中,DAO層的實體和一些資料傳輸物件(DTO),大部分屬性都是相同的,只有少部分的不同,透過mapStruct,可以讓不同實體之間的轉換變的簡單。我們只需要按照約定的方式進行配置即可。
大家的命名都不一樣,我個人是習慣把資料庫的DO物件叫Entity實體。
返回前端的叫VO。
把Entity複製到VO並做一些操作或者轉換,再返回前端,都會用到。
安裝
1、引用
唯一需要注意的就是如果配合Lombok,需要在編譯原始碼的外掛上做好配置。
<properties>
<mapstruct.version>1.3.0.Final</mapstruct.version>
</properties>
<!-- MapStruct核心,包含了一些必要的註解-->
<dependencies>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>${mapstruct.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler-plugin.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<compilerVersion>${java.version}</compilerVersion>
<fork>true</fork>
<encoding>${project.build.sourceEncoding}</encoding>
<verbose>true</verbose>
<annotationProcessorPaths>
<!-- 同時用Lombok,需要將Lombok放前面 -->
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</path>
<!-- MapStruct編譯,註解處理器,根據註解自動生成Mapper的實現 -->
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${mapstruct.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
2、定義轉換介面
@Mapper
public interface OrderConvertor {
OrderConvertor INSTANCE = Mappers.getMapper(OrderConvertor.class);
@Mapping(source = "student.birthday", target = "birthday", dateFormat = "yyyy-MM-dd HH:mm:ss") // 指定時間格式
@Mapping(target = "name", source = "student.name", defaultValue = "張三") //預設值
OrderVo toVo(OrderEntity order);
}
target表示目標屬性名,source表示源屬性名,一般在目標屬性和源屬性不同時使用,相同的屬性名會自動進行對映。
MapStruct會自動生成對應介面的實現,並自動完成屬性對映關係,List會自動進行批次處理。
3、使用時
@Service
public class OrderService {
public List<OrderVo> getOrderList() {
// 獲取資料庫資料
List<OrderEntity> result = selectOrderList();
// 引數轉換
return OrderConvertor.INSTANCE.toVo(result);
}
}
下面是我常用的一些功能記錄
1、新增為Spring的Component元件
@Mapper(componentModel = "spring")
2、List轉換為String
類註解加上引用
@Mapper(imports = {Collectors.class, TelegramGroupEntity.class})
程式碼裡面:使用表示式,轉換為字串
@Mapping(target = "groupStr", expression = "java(source.getBindGroups()!= null? source.getBindGroups().stream().map(TelegramGroupEntity::getName).collect(Collectors.joining(\", \")) : null)")
AcceptanceBankVo convert(AcceptanceBankEntity source);
直接轉換List為換行的String
@Mapping(target = "groupStr", expression = "java(source.getBindGroups()!= null? source.getBindGroups().stream().map(TelegramGroupEntity::getName).collect(Collectors.joining(\"\\n\")) : null)")
直接呼叫方法
@Mapper(imports = {Collectors.class, TelegramGroupEntity.class, IndiaDateUtil.class})
public interface TransferBankConvert {
TransferBankConvert INSTANCE = Mappers.getMapper(TransferBankConvert.class);
@Mapping(target = "timeAgo", expression = "java(source.getLastActiveTime()!= null? IndiaDateUtil.getTimeAgo(source.getLastActiveTime(),\"Asia/Kolkata\") : null)")
TransferBankVo convert(TransferBankEntity source);
}
3、獲取時間
@Mapping(target = "recordTime",expression = "java(new java.util.Date())")
4、空檢查
@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
5、列舉對映String和string到列舉
int轉列舉的value
@Mapper(imports = {AccptanceRoleTypeEnum.class}) // 加到類上引用進來
@Mapping(target = "roleText", expression = "java(AccptanceRoleTypeEnum.getItemValue(source.getRole()))")
列舉上加上:
/**
* 根據Value取描述
* @param value
* @return
*/
public static String getItemValue(Integer value) {
AccptanceRoleTypeEnum match = Stream.of(values()).filter(item -> item.value.equals(value)).findAny().orElse(null);
return match == null ? null : match.getDesc();
}
6、Fill同物件填充新物件,把source填充到target裡面,和以前的beancopy一樣的。
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE,
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
@Mappings({
@Mapping(target = "id", ignore = true),
@Mapping(target = "createTime", ignore = true),
@Mapping(target = "updateTime", ignore = true)
})
void fill(TelegramGroupRoleEntity source, @MappingTarget TelegramGroupRoleEntity target);
要忽略空值填充
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
void update(DTO dto, @MappingTarget Bean bean);
7、Map提取,還是用表示式最簡單
@Mappings({
@Mapping(expression = "java(mapConfig.getOrDefault(\"INPAY_RATES\",""))", target = "inpayRates"),
@Mapping(expression = "java(mapConfig.getOrDefault(\"AUTO_CREDIT\",""))", target = "autoCredit")
})
TelegramGroupWithConfigVo convert(TelegramGroupEntity entity);
8、空值判斷
@Mapping(target = "targetField", expression = "java( sourceField == null || sourceField.isEmpty() ? null : sourceField )") 來將空字串對映為 null
更多內容請關注我的公眾號:青塬科技。