亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中MapStruct對象映射的實現(xiàn)

 更新時間:2024年12月06日 09:46:17   作者:沙坪壩、黃師傅  
MapStruct是一種Java實體類映射框架,本文就來介紹一下Java中MapStruct對象映射的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下

簡介

MapStruct是一種實體類映射框架,能夠通過Java注解將一個實體類的屬性安全地賦值給另一個實體類。有了mapstruct,只需要定義一個映射器接口,聲明需要映射的方法,在編譯過程中,mapstruct會自動生成該接口的實現(xiàn)類,實現(xiàn)將源對象映射到目標對象的效果。

MapStruct是基于JSR 269實現(xiàn)的,JSR 269是JDK引進的一種規(guī)范。有了它,能夠實現(xiàn)在編譯期處理注解,并且讀取、修改和添加抽象語法樹中的內(nèi)容。JSR 269使用Annotation Processor在編譯期間處理注解,Annotation Processor相當于編譯器的一種插件,因此又稱為插入式注解處理。官網(wǎng)通道 | Github

優(yōu)點

  • 安全性高‌:由于映射是在編譯期間實現(xiàn)的,如果編譯器能夠通過,運行期就不會報錯。

  • 高性能:編譯時生成bean映射的實現(xiàn)類,通過使?普通?法(getter/setter)調(diào)??不是反射來快速執(zhí)?。

缺點

  • 使用復雜度:對于更復雜的映射,需要開發(fā)人員編寫自定義映射接口和函數(shù)。

同類對比

映射工具

實現(xiàn)機制

性能對比

備注

Dozer

反射機制

使用遞歸將數(shù)據(jù)從一個對象復制到另一個對象

Orika

反射機制

同Dozer,不過Orika 使用字節(jié)碼生成

ModelMapper

反射機制

簡單易用,它根據(jù)約定確定對象之間的映射方式

JMapper

編譯生成

基于Javassist 的Java映射框架

MapStruct

編譯生成

在編譯時生成bean映射,以確保高性能、徹底的錯誤檢查

快速入門

Maven依賴

<!-- 定義版本 -->
  <properties>
      <org.mapstruct.version>1.6.0</org.mapstruct.version>
      <org.projectlombok.mapstruct.version>0.2.0</org.projectlombok.mapstruct.version>
  </properties>

<!-- 依賴包 -->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>${org.mapstruct.version}</version>
</dependency>

  <!--MapStruct會用到對象中的get、set方法,但get、set方法又需要lombok來生成。因此需要控制這兩者工作順序-->
 <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok-mapstruct-binding</artifactId>
      <version>${org.projectlombok.mapstruct.version}</version>
 </dependency>

編譯插件

<!-- 方式一-->
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <version>${org.mapstruct.version}</version>
    <scope>provided</scope>
</dependency>
  
<!-- 方式二-->
  <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>17</source>
                <target>17</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

Model定義

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserDTO implements Serializable {
    private Integer id;
    private String userName;
    private String password;
    private Integer age;
    private String address;
    private String email;
    private List<UserRole> roles;
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserVO implements Serializable {
    private Integer id;
    private String name;
    private String pwd;
    private Integer age;
    private String email;
    private List<UserRole> roles;
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserRole implements Serializable {
    private Integer roleId;
    private String roleName;
    private String remark;
}

Mapper定義

//@Mapper(componentModel = "spring")
@Mapper
public interface MapStructMapper {

    MapStructMapper INSTANCE = Mappers.getMapper(MapStructMapper.class);

    /**
     * 單個對象轉換
     * @param userDTO
     * @return
     */
    UserVO userDtoToVO(UserDTO userDTO);

    /**
     * 集合對象轉換
     * @param userDTO
     * @return
     */
    List<UserVO> userDtoToVOList(List<UserDTO> userDTO);

}

重要:SpringBoot項目可以使用@Mapper(componentModel = "spring")的方式將bean交給spring容器進行管理,因此可以不用寫MapStructMapper INSTANCE = Mappers.getMapper(MapStructMapper.class);

轉換調(diào)用

    public void mapStructConvertTest(){
        // 初始化用戶
        UserDTO userDTO = this.instanceUser();
        UserVO userVO = MapStructMapper.INSTANCE.userDtoToVO(userDTO);
        log.info("userVO:{}", JSON.toJSONString(userVO));
    }

場景示例

常規(guī)映射

@Mapper
public interface MapStructMapper {

    MapStructMapper INSTANCE = Mappers.getMapper(MapStructMapper.class);

    UserVO userDtoToVO(UserDTO userDTO);

}

集合映射

@Mapper
public interface MapStructMapper {

    MapStructMapper INSTANCE = Mappers.getMapper(MapStructMapper.class);

    List<UserVO> userDtoToVOList(List<UserDTO> userDTO);

}

重要:集合轉換時,必須先有單個對象的轉換函數(shù)。并且Mapper中只能有一個同類的原對象與目標對象的轉換,否則集合轉換不知道取哪一個單對象轉換函數(shù)。

單字段映射

@Mapping(target = "pwd", source = "password")
UserVO userDtoToVO(UserDTO userDTO);

多字段映射

@Mappings({
  @Mapping(target = "pwd", source = "password"),
  @Mapping(target = "name", source = "userName"),
})
UserVO userDtoToVOMoreField(UserDTO userDTO);

忽略字段

@Mapping(target = "email", ignore = true)
UserVO userDtoToVOIgnoreField(UserDTO userDTO);

常量值映射

@Mapping(target = "constant", constant = "OK")
UserVO newUserWithConstant(UserDTO userDTO);

默認值映射

@Mapping(source = "email", target = "email", defaultValue = "默認值")
UserVO userDtoToVONullDefaultValue(UserDTO userDTO);

表達式映射

@Mapping(target = "fullName", expression = "java(userDTO.getUserName() + ' ' + userDTO.getAddress())")
UserVO userDtoToVOExpression(UserDTO userDTO);
@Mapping(target = "email", 
expression = "java(!userDTO.getEmail().isEmpty()? \"不為空\" : \"為空\")")
UserVO userDtoToVOWithCondition(UserDTO userDTO);

執(zhí)行函數(shù)

@Mapping(target = "email", source = "email", qualifiedByName = "toUpperCase")
UserVO emailToUpperCase(UserDTO userDTO);

@Named("toUpperCase")
default String toUpperCase(String value) {
    // 轉換大寫
    return value == null ? null : value.toUpperCase();
}

深拷貝

@Mapper(componentModel = "spring",mappingControl = DeepClone.class)
public interface MapStructMapper {
  
}

說明:mappingControl = DeepClone.class 是指定深拷貝模式,不指定則默認淺拷貝,淺拷貝時集合類是底層是調(diào)用Array 的copy 方法。如果是深拷貝模式,MapStruct框架會生成集合遍歷代碼,集合中元素如果是引用類型會生成引用類型轉換代碼,層層轉換,深度拷貝。集合類拷貝的限制比較多,不支持多層嵌套集合類深拷貝,而且要求源字段和目標字段集合類型嚴格一致。

淺拷貝 :只復制對象的引用,而不會復制對象本身的內(nèi)容。如果更改了原始對象的一個地址,DTO中的地址也會跟著改變,因為它們指向的是同一個對象。

深拷貝:會遞歸地復制對象的所有內(nèi)容,包括嵌套的對象。即使你更改了原始對象中的數(shù)據(jù),DTO中的數(shù)據(jù)也不會受到影響。

逆向映射

    /**
     * 單個對象映射
     * @param userDTO
     * @return
     */

    UserVO userDtoToVO(UserDTO userDTO);

    /**
     * 逆向映射
     * @param userVO  源 VO 對象
     * @return 目標 DTO 對象
     */
    @InheritInverseConfiguration
    UserDTO userVOToDto(UserVO userVO);

說明:正向函數(shù)有業(yè)務邏輯處理或屬性類型不匹配的不能逆向映射

映射后執(zhí)行動作

 @AfterMapping
default void afterMapping(UserDTO userDTO, @MappingTarget UserVO userVO) {
    // Add custom post-mapping logic here
    userVO.setId(10000);
    System.out.println("afterMapping:id設置為:"+userVO.getId());
}

延伸內(nèi)容

MapStruct  Plus 是 MapStruct 的增強工具,在 MapStruct 的基礎上,實現(xiàn)了自動生成 Mapper 接口的功能,并強化了部分功能,使 Java 類型轉換更加便捷、優(yōu)雅。官網(wǎng)通道 | GitHub

Maven依賴

<properties>
    <mapstruct-plus.version>1.4.5</mapstruct-plus.version>
</properties>
  
<dependency>
        <groupId>io.github.linpeilie</groupId>
        <artifactId>mapstruct-plus-spring-boot-starter</artifactId>
        <version>${mapstruct-plus.version}</version>
    </dependency>

新增配置類

@ComponentModelConfig(componentModel = "default")
public class MapperConfiguration {
}

對象映射

@AutoMapper(target = UserDto.class)
@Data
public class User {
    // ...
}

轉換Map

@AutoMapMapper
@Data
public class MapModelB {

    private Date date;

}

一個類轉換為多個類

@Data
@AutoMappers({
    @AutoMapper(target = UserDto.class),
    @AutoMapper(target = UserVO.class)
})
public class User {
    // fields
}

循環(huán)嵌套

@Data
@AutoMapper(target = TreeNodeDto.class, cycleAvoiding = true)
public class TreeNode {
    private TreeNode parent;
    private List<TreeNode> children;
}

@Data
@AutoMapper(target = TreeNode.class, cycleAvoiding = true)
public class TreeNodeDto {
    private TreeNodeDto parent;
    private List<TreeNodeDto> children;
}

到此這篇關于Java中MapStruct對象映射的實現(xiàn)的文章就介紹到這了,更多相關MapStruct對象映射內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java中for循環(huán)的執(zhí)行過程分析

    Java中for循環(huán)的執(zhí)行過程分析

    這篇文章主要介紹了Java中for循環(huán)的執(zhí)行過程,實例分析了for循環(huán)的執(zhí)行原理與順序,對于深入理解Java具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • 如何設置Spring Boot測試時的日志級別

    如何設置Spring Boot測試時的日志級別

    Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發(fā)過程。該框架使用了特定的方式來進行配置,從而使開發(fā)人員不再需要定義樣板化的配置。下面我們來一起學習一下吧
    2019-06-06
  • java在pdf中生成表格的方法

    java在pdf中生成表格的方法

    這篇文章主要介紹了java在pdf中生成表格的方法,需要的朋友可以參考下
    2015-11-11
  • Java?中不全部使用?Static?方法的理由

    Java?中不全部使用?Static?方法的理由

    這篇文章主要介紹了Java?中不全部使用?Static?方法的理由,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • Java Socket實現(xiàn)的傳輸對象功能示例

    Java Socket實現(xiàn)的傳輸對象功能示例

    這篇文章主要介紹了Java Socket實現(xiàn)的傳輸對象功能,結合具體實例形式分析了java socket傳輸對象的原理及接口、客戶端、服務器端相關實現(xiàn)技巧,需要的朋友可以參考下
    2017-06-06
  • Java基本數(shù)據(jù)類型和運算符詳解

    Java基本數(shù)據(jù)類型和運算符詳解

    這篇文章主要介紹了Java基本數(shù)據(jù)類型和運算符,結合實例形式詳細分析了java基本數(shù)據(jù)類型、數(shù)據(jù)類型轉換、算術運算符、邏輯運算符等相關原理與操作技巧,需要的朋友可以參考下
    2020-02-02
  • Mybatis注解方式@Insert的用法

    Mybatis注解方式@Insert的用法

    這篇文章主要介紹了Mybatis注解方式@Insert的用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 深入了解Spring中最常用的11個擴展點

    深入了解Spring中最常用的11個擴展點

    我們一說到spring,可能第一個想到的是?IOC(控制反轉)?和?AOP(面向切面編程)。除此之外,我們在使用spring的過程中,有沒有發(fā)現(xiàn)它的擴展能力非常強。今天就來跟大家一起聊聊,在Spring中最常用的11個擴展點
    2022-09-09
  • 教你怎么用java實現(xiàn)客戶端與服務器一問一答

    教你怎么用java實現(xiàn)客戶端與服務器一問一答

    這篇文章主要介紹了教你怎么用java實現(xiàn)客戶端與服務器一問一答,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-04-04
  • apollo更改配置刷新@ConfigurationProperties配置類

    apollo更改配置刷新@ConfigurationProperties配置類

    這篇文章主要為大家介紹了apollo更改配置刷新@ConfigurationProperties配置類示例解析,apollo更改配置刷新@ConfigurationProperties配置類
    2023-04-04

最新評論