自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

SpringBoot與MapStruct整合,解決復雜對象轉換中的類型安全漏洞問題

開發(fā) 前端
我們在寫多層架構時,數(shù)據(jù)傳輸對象(DTO)、實體類和其他業(yè)務對象之間的轉換是不可避免的。手動編寫這些映射邏輯不僅耗時而且容易出錯。

我們在寫多層架構時,數(shù)據(jù)傳輸對象(DTO)、實體類和其他業(yè)務對象之間的轉換是不可避免的。手動編寫這些映射邏輯不僅耗時而且容易出錯。為了提高開發(fā)效率和代碼質量,我們建議引入 MapStruct 作為我們的對象映射工具。

MapStruct 的優(yōu)勢

1. 編譯時檢查

  • 類型安全: 編譯器會在編譯時檢查映射邏輯,確保源對象和目標對象的字段匹配。
  • 錯誤報告: 如果映射出現(xiàn)問題,編譯器會立即報錯,便于調試和修復。

2. 高性能

  • 無反射: 生成的映射代碼不依賴反射,執(zhí)行速度快。
  • 零運行時開銷: 不需要額外的庫或運行時組件。

3. 清晰的配置

  • 注解驅動: 使用簡潔的注解來定義映射規(guī)則,易于理解和維護。
  • 默認行為: 提供合理的默認行為,減少樣板代碼。

4. 強大的功能支持

  • 嵌套對象: 自動處理嵌套對象的映射。
  • 集合映射: 支持列表、數(shù)組等多種集合類型的映射。
  • 自定義方法: 可以通過自定義方法實現(xiàn)復雜的映射邏輯。
  • 枚舉映射: 支持枚舉類型的映射。

代碼實操

<dependencies>
    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- MapStruct -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.5.3.Final</version>
    </dependency>

    <!-- MapStruct Processor -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct-processor</artifactId>
        <version>1.5.3.Final</version>
        <scope>provided</scope>
    </dependency>

    <!-- Lombok (Optional, for reducing boilerplate code) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>1.5.3.Final</version>
                    </path>
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok-mapstruct-binding</artifactId>
                        <version>0.2.0</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

實體類 Address

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
publicclass Address {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String street;

    private String city;

    // Getters and Setters (or use Lombok)
}

實體類 User

import javax.persistence.*;
import java.util.List;

@Entity
publicclass User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private Integer age;

    private Boolean isActive;

    @OneToOne(cascade = CascadeType.ALL)
    private Address address;

    @OneToMany(cascade = CascadeType.ALL)
    private List<Address> addresses;

    // Getters and Setters (or use Lombok)
}

DTO 類 AddressDto

public class AddressDto {

    private Long id;

    private String street;

    private String city;

    // Getters and Setters (or use Lombok)
}

枚舉類 Status

public enum Status {
    ACTIVE,
    INACTIVE
}

DTO 類 UserDto

import java.util.List;

publicclass UserDto {

    private Long id;

    private String name;

    private Integer age;

    private Status status;

    private AddressDto address;

    private List<AddressDto> addresses;

    // Getters and Setters (or use Lombok)
}

創(chuàng)建兩個 Mapper 接口來分別處理 Address 到 AddressDto 的映射和 User 到 UserDto 的映射。

AddressMapper 接口

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

@Mapper(componentModel = "spring")
public interface AddressMapper {

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

    AddressDto addressToAddressDto(Address address);

    Address addressDtoToAddress(AddressDto addressDto);
}

UserMapper 接口

import org.mapstruct.*;
import org.mapstruct.factory.Mappers;

import java.util.List;

@Mapper(componentModel = "spring", uses = {AddressMapper.class})
public interface UserMapper {

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

    @Mapping(source = "address", target = "address")
    @Mapping(source = "addresses", target = "addresses")
    @Mapping(target = "status", source = "isActive", qualifiedByName = "activeToStatus")
    @Mapping(target = "age", defaultValue = "18") // Default value if age is null
    UserDto userToUserDto(User user);

    @Mapping(source = "address", target = "address")
    @Mapping(source = "addresses", target = "addresses")
    @Mapping(target = "isActive", source = "status", qualifiedByName = "statusToActive")
    User userDtoToUser(UserDto userDto);

    @Named("activeToStatus")
    default Status activeToStatus(Boolean isActive) {
        return isActive != null && isActive ? Status.ACTIVE : Status.INACTIVE;
    }

    @Named("statusToActive")
    default Boolean statusToActive(Status status) {
        return status == Status.ACTIVE;
    }
}

代碼解讀

  1. 默認值 (defaultValue):
  • 在 UserMapper 中,@Mapping(target = "age", defaultValue = "18") 指定了如果 User 對象中的 age 屬性為 null,則默認值為 18。
  1. 條件映射 (qualifiedByName):
  • 使用 @Named 注解定義了兩個方法 activeToStatus 和 statusToActive,用于在 User 和 UserDto 之間進行狀態(tài)轉換。
  • 這些方法通過 @Mapping(target = ..., source = ..., qualifiedByName = ...) 被引用。
  1. 自定義方法:
  • 自定義方法 activeToStatus 和 statusToActive 直接在 UserMapper 接口中實現(xiàn),提供了靈活的數(shù)據(jù)轉換邏輯。
  1. 枚舉映射:
  • 通過自定義方法將布爾類型的 isActive 字段映射到枚舉類型的 Status 字段,并反之。

常見問題與解決方案

MapStruct 是否支持循環(huán)引用?

MapStruct 默認不支持循環(huán)引用,但可以通過自定義方法或使用 @AfterMapping 注解來處理循環(huán)引用的情況。

如何處理不同命名的屬性?

使用 @Mapping 注解中的 source 和 target 屬性來指定不同的屬性名稱:

@Mapping(source = "entityPropertyName", target = "dtoPropertyName")

如何處理日期格式轉換?

使用 @Mapping 注解中的 dateFormat 屬性:

@Mapping(source = "dateField", dateFormat = "yyyy-MM-dd")

如何處理集合過濾?

使用 @IterableMapping 注解結合 qualifiedByName 或 qualifiedBy 來過濾集合:

@IterableMapping(qualifiedByName = "filterNulls")
List<String> filterStrings(List<String> strings);

@Named("filterNulls")
default String filterNulls(String string) {
    return string != null ? string : "";
}


責任編輯:武曉燕 來源: Java知識日歷
相關推薦

2010-04-20 09:44:24

2013-05-07 13:32:25

2020-08-16 08:50:03

Zoom網(wǎng)絡攻擊漏洞

2009-07-05 11:27:09

2023-07-28 12:44:04

2013-06-03 14:39:01

2011-03-31 13:46:51

2010-11-01 13:38:11

2010-07-26 15:37:12

telnet安全漏洞

2025-03-06 08:37:01

2011-05-30 09:19:00

2022-07-28 16:47:32

漏洞網(wǎng)絡安全風險

2009-11-06 10:09:55

2013-01-30 09:56:56

2017-06-08 12:25:52

2022-09-02 08:17:40

MapStruct代碼工具

2015-03-19 09:36:39

2014-06-03 09:23:41

2014-06-03 11:36:18

2023-07-10 12:06:53

點贊
收藏

51CTO技術棧公眾號