欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中基于注解的代碼生成工具MapStruct映射使用詳解

 更新時間:2025年02月10日 09:04:49   作者:Andya  
MapStruct?作為一個基于注解的代碼生成工具,為我們提供了一種更加優(yōu)雅、高效的解決方案,本文主要為大家介紹了它的具體使用,感興趣的可以了解下

介紹

在 Java 開發(fā)中,我們經(jīng)常需要在不同的 Java Bean 之間進行數(shù)據(jù)映射,比如從實體類(Entity)到數(shù)據(jù)傳輸對象(DTO)的轉換。傳統(tǒng)的做法是手動編寫大量的 setter 和 getter 方法來完成屬性的賦值,這種方式不僅繁瑣,而且容易出錯。MapStruct 作為一個基于注解的代碼生成工具,為我們提供了一種更加優(yōu)雅、高效的解決方案。它在編譯時自動生成映射代碼,避免了運行時反射帶來的性能開銷,同時保證了類型安全。

優(yōu)缺點

優(yōu)點

  • 高性能:MapStruct 在編譯階段生成映射代碼,運行時直接調(diào)用這些代碼,避免了反射的使用,從而顯著提高了性能。
  • 類型安全:由于映射代碼是在編譯時生成的,編譯器會對類型進行檢查,因此可以在編譯階段發(fā)現(xiàn)類型不匹配等錯誤,避免了運行時異常。
  • 代碼簡潔:使用 MapStruct 只需要定義映射接口和使用注解進行配置,無需手動編寫大量的映射邏輯,大大減少了代碼量,提高了開發(fā)效率。

缺點

  • 學習成本:需要學習 MapStruct 提供的各種注解及其使用方法,對于初學者來說可能有一定的學習曲線。
  • 依賴管理:需要在項目中引入 MapStruct 的相關依賴,增加了項目的依賴管理復雜度。

核心注解及詳細使用語法說明

@Mapper

  • 作用:用于標記一個接口為映射接口,MapStruct 會在編譯時為該接口生成具體的實現(xiàn)類。
  • 使用語法
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface UserMapper {
    // 通過 Mappers.getMapper 方法獲取映射接口的實例
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    // 定義從 UserEntity 到 UserDTO 的映射方法
    UserDTO toDTO(UserEntity entity);
    // 定義從 UserDTO 到 UserEntity 的映射方法
    UserEntity toEntity(UserDTO dto);
}

@Mapping

  • 作用:用于指定源對象和目標對象之間的屬性映射關系,當源對象和目標對象的屬性名不一致時,可以使用該注解進行顯式映射。
  • 使用語法
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    // 使用 @Mapping 注解指定 entityId 映射到 id,entityName 映射到 name
    @Mapping(source = "entityId", target = "id")
    @Mapping(source = "entityName", target = "name")
    UserDTO toDTO(UserEntity entity);

    // 反向映射
    @Mapping(source = "id", target = "entityId")
    @Mapping(source = "name", target = "entityName")
    UserEntity toEntity(UserDTO dto);
}

@Mappings

  • 作用:@Mappings 是 @Mapping 的集合形式,用于一次性指定多個屬性映射關系。
  • 使用語法
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    @Mappings({
        @Mapping(source = "entityId", target = "id"),
        @Mapping(source = "entityName", target = "name")
    })
    UserDTO toDTO(UserEntity entity);

    @Mappings({
        @Mapping(source = "id", target = "entityId"),
        @Mapping(source = "name", target = "entityName")
    })
    UserEntity toEntity(UserDTO dto);
}

@Context

  • 作用:用于在映射過程中傳遞上下文信息,比如一些輔助對象,這些對象可以在映射方法中使用。
  • 使用語法
import org.mapstruct.Mapper;
import org.mapstruct.Context;
import org.mapstruct.factory.Mappers;
import java.util.Locale;

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    // 使用 @Context 注解傳遞 Locale 對象作為上下文信息
    UserDTO toDTO(UserEntity entity, @Context Locale locale);
}

@AfterMapping

  • 作用:用于在映射完成后執(zhí)行自定義的邏輯,比如對目標對象的某些屬性進行額外的處理。
  • 使用語法
import org.mapstruct.Mapper;
import org.mapstruct.AfterMapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    UserDTO toDTO(UserEntity entity);

    // 使用 @AfterMapping 注解定義映射完成后的自定義邏輯
    @AfterMapping
    default void afterMapping(@MappingTarget UserDTO dto, UserEntity entity) {
        // 將源對象的 firstName 和 lastName 拼接后賦值給目標對象的 fullName 屬性
        dto.setFullName(entity.getFirstName() + " " + entity.getLastName());
    }
}

Demo示例

公共基本類定義

import lombok.Data;

// 用戶實體類
@Data
public class UserEntity {
    private Long id;
    private String name;
    private Integer age;
    private String firstName;
    private String lastName;
    private AddressEntity address;
    private Long entityId;
    private String entityName;
}

// 用戶數(shù)據(jù)傳輸對象類
@Data
public class UserDTO {
    private Long id;
    private String name;
    private Integer age;
    private String fullName;
    private AddressDTO address;
    private Long entityId;
    private String entityName;
}

// 地址實體類
@Data
public class AddressEntity {
    private String street;
    private String city;
}

// 地址數(shù)據(jù)傳輸對象類
@Data
public class AddressDTO {
    private String street;
    private String city;
}

簡單映射示例

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface UserMapper {
    // 獲取映射接口的實例
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    // 從 UserEntity 到 UserDTO 的映射方法
    UserDTO toDTO(UserEntity entity);
    // 從 UserDTO 到 UserEntity 的映射方法
    UserEntity toEntity(UserDTO dto);
}

// 測試代碼
public class MainSimpleMapping {
    public static void main(String[] args) {
        UserEntity userEntity = new UserEntity();
        userEntity.setId(1L);
        userEntity.setName("John");
        userEntity.setAge(25);

        // 使用映射接口的實例進行映射
        UserDTO userDTO = UserMapper.INSTANCE.toDTO(userEntity);
        System.out.println("簡單映射示例結果:");
        System.out.println("UserDTO: id=" + userDTO.getId() + ", name=" + userDTO.getName() + ", age=" + userDTO.getAge());
    }
}

輸出結果:

簡單映射示例結果:
UserDTO: id=1, name=John, age=25

字段名不一致的映射示例

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    @Mapping(source = "entityId", target = "id")
    @Mapping(source = "entityName", target = "name")
    UserDTO toDTO(UserEntity entity);

    @Mapping(source = "id", target = "entityId")
    @Mapping(source = "name", target = "entityName")
    UserEntity toEntity(UserDTO dto);
}

// 測試代碼
public class MainFieldNameMismatch {
    public static void main(String[] args) {
        UserEntity userEntity = new UserEntity();
        userEntity.setEntityId(1L);
        userEntity.setEntityName("John");
        userEntity.setAge(25);

        UserDTO userDTO = UserMapper.INSTANCE.toDTO(userEntity);
        System.out.println("字段名不一致映射示例結果:");
        System.out.println("UserDTO: id=" + userDTO.getId() + ", name=" + userDTO.getName() + ", age=" + userDTO.getAge());
    }
}

輸出結果:

字段名不一致映射示例結果:
UserDTO: id=1, name=John, age=25

嵌套對象映射示例

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    UserDTO toDTO(UserEntity entity);
    UserEntity toEntity(UserDTO dto);

    AddressDTO toDTO(AddressEntity entity);
    AddressEntity toEntity(AddressDTO dto);
}

// 測試代碼
public class MainNestedObjectMapping {
    public static void main(String[] args) {
        AddressEntity addressEntity = new AddressEntity();
        addressEntity.setStreet("123 Main St");
        addressEntity.setCity("New York");

        UserEntity userEntity = new UserEntity();
        userEntity.setId(1L);
        userEntity.setName("John");
        userEntity.setAddress(addressEntity);

        UserDTO userDTO = UserMapper.INSTANCE.toDTO(userEntity);
        System.out.println("嵌套對象映射示例結果:");
        System.out.println("UserDTO: id=" + userDTO.getId() + ", name=" + userDTO.getName());
        System.out.println("AddressDTO: street=" + userDTO.getAddress().getStreet() + ", city=" + userDTO.getAddress().getCity());
    }
}

輸出結果:

嵌套對象映射示例結果:
UserDTO: id=1, name=John
AddressDTO: street=123 Main St, city=New York

自定義映射邏輯示例

import org.mapstruct.Mapper;
import org.mapstruct.AfterMapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    UserDTO toDTO(UserEntity entity);

    @AfterMapping
    default void afterMapping(@MappingTarget UserDTO dto, UserEntity entity) {
        dto.setFullName(entity.getFirstName() + " " + entity.getLastName());
    }
}

// 測試代碼
public class MainCustomMappingLogic {
    public static void main(String[] args) {
        UserEntity userEntity = new UserEntity();
        userEntity.setId(1L);
        userEntity.setFirstName("John");
        userEntity.setLastName("Doe");

        UserDTO userDTO = UserMapper.INSTANCE.toDTO(userEntity);
        System.out.println("自定義映射邏輯示例結果:");
        System.out.println("UserDTO: id=" + userDTO.getId() + ", fullName=" + userDTO.getFullName());
    }
}

輸出結果:

自定義映射邏輯示例結果:
UserDTO: id=1, fullName=John Doe

使用上下文示例

import org.mapstruct.Mapper;
import org.mapstruct.Context;
import org.mapstruct.factory.Mappers;
import java.util.Locale;

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    UserDTO toDTO(UserEntity entity, @Context Locale locale);

    default String localize(String value, @Context Locale locale) {
        // 根據(jù) locale 進行本地化處理
        return value;
    }
}

// 測試代碼
public class MainWithContext {
    public static void main(String[] args) {
        UserEntity userEntity = new UserEntity();
        userEntity.setId(1L);
        userEntity.setName("John");

        Locale locale = Locale.US;
        UserDTO userDTO = UserMapper.INSTANCE.toDTO(userEntity, locale);
        System.out.println("使用上下文示例結果:");
        System.out.println("UserDTO: id=" + userDTO.getId() + ", name=" + userDTO.getName());
    }
}

輸出結果:

使用上下文示例結果:
UserDTO: id=1, name=John

通過以上示例可以看到,使用 MapStruct 能夠方便快捷地完成 Java Bean 之間的映射,同時結合 Lombok 的 @Data 注解進一步簡化了代碼。并且從輸出結果可以直觀地驗證各個映射場景的正確性。

到此這篇關于Java中基于注解的代碼生成工具MapStruct映射使用詳解的文章就介紹到這了,更多相關Java MapStruct內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論