Java 實體-實體的映射框架

一、Object mapping 的技術分類:

  • 運行期 反射調用set/get 或者是直接對成員變量賦值 。 該方式通過invoke執行賦值 *,實現時一般會採用beanutil, Javassist等開源庫。這類的代表:Dozer,ModelMaper

  • 編譯期 動態生成set/get代碼的class文件 ,在運行時直接調用該class文件。* 該方式實際上扔會存在set/get代碼,只是不需要自己寫了。 這類的代表:MapStruct,Selma,Orika ### 主要框架性能對比: 每秒鐘執行的object mapping越多越好。
    這裏寫圖片描述
    明顯可以看出通過在運行期進行反射的方式執行,性能遠不如編譯器生成class的方式;

MapStruct 與 Selma的對比: https://java.libhunt.com/project/mapstruct/vs/selma
與 ModelMapper的對比:https://java.libhunt.com/project/mapstruct/vs/modelmapper

綜合比較性能、問題排查、文檔、成熟度、擴展性等因素來考慮,MapStruct 是一個不錯的選擇;

二、Maven依賴與配置:

    <properties>
        <java.version>1.8</java.version>
        <org.mapstruct.version>1.2.0.Final</org.mapstruct.version>
    </properties>
    <dependency>
       <groupId>org.mapstruct</groupId>
       <artifactId>mapstruct-jdk8</artifactId>
       <version>${org.mapstruct.version}</version>
   </dependency>
<plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <version>3.5.1</version>
           <configuration>
               <source>${java.version}</source>
               <target>${java.version}</target>
               <encoding>${java.encoding}</encoding>
               <annotationProcessorPaths>
                   <path>
                       <groupId>org.mapstruct</groupId>
                       <artifactId>mapstruct-processor</artifactId>
                       <version>${org.mapstruct.version}</version>
                   </path>
               </annotationProcessorPaths>
           </configuration>
    </plugin>

或者可以兩個都寫成依賴,不需要寫成maven插件的形式,後面的依賴用於生成運行期的class實現類,如下:

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
            <scope>provided</scope>
        </dependency>

三、MapStruct的基本使用:

@Mapper(componentModel = "spring")
public interface MonitorAppGroupIdcDTOMapper {
    MonitorAppGroupIdcDTOMapper MAPPER = Mappers.getMapper(MonitorAppGroupIdcDTOMapper.class);
    void mapping(MonitorAppGroupIdcDTO source, @MappingTarget MonitorAppGroupIdcDTO dest);
}

編譯後生成的部分代碼結構:

@Component
public class MonitorAppGroupIdcDTOMapperImpl implements MonitorAppGroupIdcDTOMapper {
    public MonitorAppGroupIdcDTOMapperImpl() {
    }

    public void mapping(MonitorAppGroupIdcDTO source, MonitorAppGroupIdcDTO dest) {
        if(source != null) {
            dest.setId(source.getId());
            dest.setGmtCreate(source.getGmtCreate());
            ...
        }
    }
}

可以看出MapStruct還需要依賴對象的get/set方法,有時候編寫一堆的get/set方法看上去很不美觀,期望能通過自動生成的方式插入get/set方法,其解決方案是使用lombok。mapstrcut官網也有二者結合的例子: https://github.com/mapstruct/mapstruct/issues/510 Lombok帶來的問題是,如果我們期望通過公有的get/set方法範圍私有屬性時,IDE會提示方法不存在,這個時候我們可以下載安裝Intellij Idea中的”Lombok plugin”來解決,但是這種方案帶來了一定的繁瑣性。比較好的方式是,對於DO或者DTO中的屬性,如果屬性爲私有屬性,需要通過get/set方法來訪問的,那麼就手工生成get/set方法,如果屬性本身爲共有屬性的,那麼就可以藉助Lombok來自動生成get/set方法了。

四、MapStruct的屬性與方法:

  1. @Mapper註解的componentModel屬性
    componentModel 屬性用於指定自動生成的接口實現類的組件類型。這個屬性支持四個值:
default: 這是默認的情況,mapstruct不使用任何組件類型, 可以通過Mappers.getMapper(Class)方式獲取自動生成的實例對象。
cdi: the generated mapper is an application-scoped CDI bean and can be retrieved via @Inject
spring: 生成的實現類上面會自動添加一個@Component註解,可以通過Spring的 @Autowired方式進行注入
jsr330: 生成的實現類上會添加@javax.inject.Named 和@Singleton註解,可以通過 @Inject註解獲取。

五、下面我們先來看下代碼,多對象映射如下所示:

@Mapper(componentModel = "spring")
//@Mapper
public interface GoodInfoMapper
{
    //public static GoodInfoMapper MAPPER = Mappers.getMapper(GoodInfoMapper.class);

    @Mappings({
            @Mapping(source = "type.name",target = "typeName"),
            @Mapping(source = "good.id",target = "goodId"),
            @Mapping(source = "good.title",target = "goodName"),
            @Mapping(source = "good.price",target = "goodPrice")
    })
    public GoodInfoDTO from(GoodInfoBean good, GoodTypeBean type);
}

原文地址 https://blog.csdn.net/paincupid/article/details/71247255

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章