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

SpringBoot實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)換的四種對(duì)象映射方案

 更新時(shí)間:2025年06月03日 08:37:48   作者:風(fēng)象南  
在項(xiàng)目開(kāi)發(fā)中,對(duì)象之間的相互轉(zhuǎn)換是一個(gè)高頻操作,尤其在分層架構(gòu)的系統(tǒng)中,數(shù)據(jù)在實(shí)體對(duì)象(Entity)、數(shù)據(jù)傳輸對(duì)象(DTO)、值對(duì)象(VO)之間的轉(zhuǎn)換尤為常見(jiàn),選擇一個(gè)高效、可靠的對(duì)象映射方案對(duì)提高系統(tǒng)性能和開(kāi)發(fā)效率至關(guān)重要,本文將介紹4種對(duì)象映射方案

方案一:手動(dòng)映射

手動(dòng)映射是最基礎(chǔ)也是最直接的方法,通過(guò)顯式編寫(xiě)代碼將一個(gè)對(duì)象的屬性復(fù)制到另一個(gè)對(duì)象。

實(shí)現(xiàn)方式

首先定義兩個(gè)示例類(lèi):

// 用戶實(shí)體類(lèi)
@Entity
@Table(name = "users")
public class UserEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private String email;
    private String phoneNumber;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
    // getter和setter省略
}

// 用戶DTO類(lèi)
public class UserDTO {
    private Long id;
    private String username;
    private String email;
    private String phone; // 注意命名差異
    private LocalDateTime registerTime; // 映射自createTime
    // getter和setter省略
}

手動(dòng)映射實(shí)現(xiàn):

public class UserMapper {
    
    public static UserDTO toDTO(UserEntity entity) {
        if (entity == null) {
            return null;
        }
        
        UserDTO dto = new UserDTO();
        dto.setId(entity.getId());
        dto.setUsername(entity.getUsername());
        dto.setEmail(entity.getEmail());
        dto.setPhone(entity.getPhoneNumber()); // 不同名稱(chēng)字段映射
        dto.setRegisterTime(entity.getCreateTime()); // 語(yǔ)義轉(zhuǎn)換
        
        return dto;
    }
    
    public static UserEntity toEntity(UserDTO dto) {
        if (dto == null) {
            return null;
        }
        
        UserEntity entity = new UserEntity();
        entity.setId(dto.getId());
        entity.setUsername(dto.getUsername());
        entity.setEmail(dto.getEmail());
        entity.setPhoneNumber(dto.getPhone()); // 不同名稱(chēng)字段映射
        entity.setCreateTime(dto.getRegisterTime()); // 語(yǔ)義轉(zhuǎn)換
        
        return entity;
    }
    
    // 集合轉(zhuǎn)換方法
    public static List<UserDTO> toDTOList(List<UserEntity> entities) {
        if (entities == null) {
            return Collections.emptyList();
        }
        
        return entities.stream()
                .map(UserMapper::toDTO)
                .collect(Collectors.toList());
    }
}

優(yōu)缺點(diǎn)分析

優(yōu)點(diǎn):

  • 完全掌控映射邏輯,靈活性最高
  • 不依賴(lài)第三方庫(kù),無(wú)學(xué)習(xí)成本
  • 映射邏輯清晰直觀,易于調(diào)試
  • 性能最優(yōu),無(wú)反射開(kāi)銷(xiāo)

缺點(diǎn):

  • 代碼冗長(zhǎng),大量重復(fù)勞動(dòng)
  • 屬性變更需要手動(dòng)同步修改轉(zhuǎn)換代碼
  • 隨著對(duì)象數(shù)量增加,維護(hù)成本劇增
  • 容易出現(xiàn)人為錯(cuò)誤,如遺漏字段

方案二:MapStruct

MapStruct是一個(gè)代碼生成器,它基于約定優(yōu)于配置的方法,在編譯時(shí)生成類(lèi)型安全的對(duì)象映射代碼。

實(shí)現(xiàn)方式

1. 添加依賴(lài)

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

2. 定義映射接口

@Mapper(componentModel = "spring")
public interface UserMapStruct {
    
    @Mapping(source = "phoneNumber", target = "phone")
    @Mapping(source = "createTime", target = "registerTime")
    UserDTO toDTO(UserEntity entity);
    
    @Mapping(source = "phone", target = "phoneNumber")
    @Mapping(source = "registerTime", target = "createTime")
    UserEntity toEntity(UserDTO dto);
    
    List<UserDTO> toDTOList(List<UserEntity> entities);
    
    // 默認(rèn)值處理
    @Mapping(target = "email", defaultValue = "no-email@example.com")
    UserDTO toDTOWithDefaultEmail(UserEntity entity);
    
    // 自定義方法處理復(fù)雜轉(zhuǎn)換
    default String formatPhoneNumber(String phoneNumber) {
        if (phoneNumber == null || phoneNumber.trim().isEmpty()) {
            return null;
        }
        // 格式化電話號(hào)碼邏輯
        return phoneNumber.replaceAll("(\d{3})(\d{4})(\d{4})", "$1-$2-$3");
    }
}

3. 使用方式

@Service
public class UserService {
    
    private final UserMapStruct userMapper;
    
    @Autowired
    public UserService(UserMapStruct userMapper) {
        this.userMapper = userMapper;
    }
    
    public UserDTO getUserDTO(Long id) {
        UserEntity entity = userRepository.findById(id).orElseThrow();
        return userMapper.toDTO(entity);
    }
    
    public List<UserDTO> getAllUserDTOs() {
        List<UserEntity> entities = userRepository.findAll();
        return userMapper.toDTOList(entities);
    }
}

優(yōu)缺點(diǎn)分析

優(yōu)點(diǎn):

  • 編譯時(shí)生成代碼,運(yùn)行時(shí)性能極高
  • 編譯時(shí)類(lèi)型安全檢查,錯(cuò)誤提前發(fā)現(xiàn)
  • 代碼簡(jiǎn)潔,開(kāi)發(fā)效率高
  • 支持復(fù)雜映射和自定義轉(zhuǎn)換邏輯
  • 簡(jiǎn)化集合映射,無(wú)需手動(dòng)循環(huán)

缺點(diǎn):

  • 需要額外依賴(lài)和配置
  • 調(diào)試相對(duì)復(fù)雜(需查看生成的代碼)

方案三:ModelMapper

ModelMapper是一個(gè)靈活、強(qiáng)大的對(duì)象映射庫(kù),通過(guò)反射機(jī)制實(shí)現(xiàn)自動(dòng)映射。

實(shí)現(xiàn)方式

1. 添加依賴(lài)

<dependency>
    <groupId>org.modelmapper</groupId>
    <artifactId>modelmapper</artifactId>
    <version>3.1.1</version>
</dependency>

2. 配置ModelMapper

@Configuration
public class ModelMapperConfig {
    
    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();
        
        // 配置映射策略
        modelMapper.getConfiguration()
                .setMatchingStrategy(MatchingStrategies.STRICT)
                .setPropertyCondition(Conditions.isNotNull())
                .setFieldAccessLevel(Configuration.AccessLevel.PRIVATE)
                .setFieldMatchingEnabled(true);
        
        // 自定義字段映射
        PropertyMap<UserEntity, UserDTO> userMap = new PropertyMap<UserEntity, UserDTO>() {
            @Override
            protected void configure() {
                map().setPhone(source.getPhoneNumber());
                map().setRegisterTime(source.getCreateTime());
            }
        };
        
        modelMapper.addMappings(userMap);
        
        return modelMapper;
    }
}

3. 使用方式

@Service
public class UserService {
    
    private final ModelMapper modelMapper;
    private final UserRepository userRepository;
    
    @Autowired
    public UserService(ModelMapper modelMapper, UserRepository userRepository) {
        this.modelMapper = modelMapper;
        this.userRepository = userRepository;
    }
    
    public UserDTO getUserDTO(Long id) {
        UserEntity entity = userRepository.findById(id).orElseThrow();
        return modelMapper.map(entity, UserDTO.class);
    }
    
    public List<UserDTO> getAllUserDTOs() {
        List<UserEntity> entities = userRepository.findAll();
        return entities.stream()
                .map(entity -> modelMapper.map(entity, UserDTO.class))
                .collect(Collectors.toList());
    }
    
    public UserEntity createUser(UserDTO dto) {
        UserEntity entity = modelMapper.map(dto, UserEntity.class);
        return userRepository.save(entity);
    }
}

優(yōu)缺點(diǎn)分析

優(yōu)點(diǎn):

  • 使用簡(jiǎn)單,API友好
  • 配置靈活,支持多種映射策略
  • 運(yùn)行時(shí)動(dòng)態(tài)映射,無(wú)需預(yù)定義
  • 支持深層映射和復(fù)雜對(duì)象圖
  • 類(lèi)型轉(zhuǎn)換內(nèi)置支持

缺點(diǎn):

  • 基于反射,性能要求極高的場(chǎng)景可能不適合
  • 運(yùn)行時(shí)類(lèi)型不安全,可能產(chǎn)生運(yùn)行時(shí)異常
  • 映射邏輯不直觀,調(diào)試?yán)щy
  • 復(fù)雜映射需要額外配置

方案四:Spring BeanUtils和BeanCopier

Spring框架提供了多種Bean屬性復(fù)制工具,其中BeanUtils是基于反射的,而B(niǎo)eanCopier是基于字節(jié)碼生成的高性能方案。

實(shí)現(xiàn)方式

1. Spring BeanUtils

import org.springframework.beans.BeanUtils;

public class UserMapperWithBeanUtils {
    
    public static UserDTO toDTO(UserEntity entity) {
        if (entity == null) {
            return null;
        }
        
        UserDTO dto = new UserDTO();
        // 復(fù)制相同名稱(chēng)的屬性
        BeanUtils.copyProperties(entity, dto);
        
        // 手動(dòng)處理不同名稱(chēng)的屬性
        dto.setPhone(entity.getPhoneNumber());
        dto.setRegisterTime(entity.getCreateTime());
        
        return dto;
    }
    
    public static UserEntity toEntity(UserDTO dto) {
        if (dto == null) {
            return null;
        }
        
        UserEntity entity = new UserEntity();
        BeanUtils.copyProperties(dto, entity);
        
        // 手動(dòng)處理不同名稱(chēng)的屬性
        entity.setPhoneNumber(dto.getPhone());
        entity.setCreateTime(dto.getRegisterTime());
        
        return entity;
    }
    
    public static List<UserDTO> toDTOList(List<UserEntity> entities) {
        if (entities == null) {
            return Collections.emptyList();
        }
        
        return entities.stream()
                .map(UserMapperWithBeanUtils::toDTO)
                .collect(Collectors.toList());
    }
}

2. CGLib BeanCopier

import org.springframework.cglib.beans.BeanCopier;

public class UserMapperWithBeanCopier {
    
    // 創(chuàng)建并緩存BeanCopier實(shí)例,提高性能
    private static final BeanCopier ENTITY_TO_DTO = BeanCopier.create(UserEntity.class, UserDTO.class, false);
    private static final BeanCopier DTO_TO_ENTITY = BeanCopier.create(UserDTO.class, UserEntity.class, false);
    
    public static UserDTO toDTO(UserEntity entity) {
        if (entity == null) {
            return null;
        }
        
        UserDTO dto = new UserDTO();
        // 復(fù)制相同名稱(chēng)的屬性
        ENTITY_TO_DTO.copy(entity, dto, null);
        
        // 手動(dòng)處理不同名稱(chēng)的屬性
        dto.setPhone(entity.getPhoneNumber());
        dto.setRegisterTime(entity.getCreateTime());
        
        return dto;
    }
    
    public static UserEntity toEntity(UserDTO dto) {
        if (dto == null) {
            return null;
        }
        
        UserEntity entity = new UserEntity();
        DTO_TO_ENTITY.copy(dto, entity, null);
        
        // 手動(dòng)處理不同名稱(chēng)的屬性
        entity.setPhoneNumber(dto.getPhone());
        entity.setCreateTime(dto.getRegisterTime());
        
        return entity;
    }
}

優(yōu)缺點(diǎn)分析

Spring BeanUtils

優(yōu)點(diǎn):

  • 開(kāi)箱即用,無(wú)需額外依賴(lài)
  • 使用簡(jiǎn)單,API簡(jiǎn)潔
  • 內(nèi)置在Spring框架中
  • 支持屬性忽略功能

缺點(diǎn):

  • 基于反射,性能要求極高的場(chǎng)景可能不適合
  • 僅支持相同名稱(chēng)的屬性自動(dòng)復(fù)制
  • 不同名稱(chēng)屬性需手動(dòng)處理
  • 不支持深層嵌套對(duì)象自動(dòng)映射

CGLib BeanCopier

優(yōu)點(diǎn):

  • 性能極高,接近手動(dòng)映射
  • 基于字節(jié)碼生成,避免反射開(kāi)銷(xiāo)
  • 緩存BeanCopier實(shí)例可進(jìn)一步提升性能
  • Spring Boot默認(rèn)包含CGLib依賴(lài)

缺點(diǎn):

  • 只能復(fù)制名稱(chēng)完全相同的屬性
  • 不支持類(lèi)型轉(zhuǎn)換
  • 配置選項(xiàng)有限
  • 不同名稱(chēng)屬性仍需手動(dòng)處理
  • 文檔較少,使用門(mén)檻略高

總結(jié)

對(duì)象映射是Spring Boot應(yīng)用中的常見(jiàn)需求,選擇合適的映射方案能顯著提高開(kāi)發(fā)效率和應(yīng)用性能。

根據(jù)項(xiàng)目規(guī)模、性能要求和團(tuán)隊(duì)熟悉度選擇合適的方案,同時(shí)注意映射過(guò)程中的深淺拷貝、循環(huán)引用等問(wèn)題。

合理使用對(duì)象映射工具,可以大幅減少樣板代碼,提高代碼質(zhì)量和可維護(hù)性。

以上就是SpringBoot數(shù)據(jù)轉(zhuǎn)換的4種對(duì)象映射方案的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot對(duì)象映射的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringMVC使用MultipartResolver實(shí)現(xiàn)文件上傳

    SpringMVC使用MultipartResolver實(shí)現(xiàn)文件上傳

    MultipartResolver 用于處理文件上傳,當(dāng)收到請(qǐng)求時(shí) DispatcherServlet 的 checkMultipart() 方法會(huì)調(diào)用 MultipartResolver 的 isMultipart() 方法判斷請(qǐng)求中是否包含文件
    2023-02-02
  • Java中equalsIgnoreCase()方法的使用

    Java中equalsIgnoreCase()方法的使用

    本文主要介紹了Java中equalsIgnoreCase()方法的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 圖解JAVA中Spring Aop作用

    圖解JAVA中Spring Aop作用

    這篇文章主要介紹了Java的Spring框架下的AOP的作用,需要的朋友可以參考
    2017-04-04
  • IDEA2022.2的簡(jiǎn)介、下載與安裝、配置教程

    IDEA2022.2的簡(jiǎn)介、下載與安裝、配置教程

    IDEA是JetBrains公司推出一個(gè)集成開(kāi)發(fā)工具,是Java開(kāi)發(fā)工具中的翹楚,基于這個(gè)開(kāi)發(fā)工具可以快速開(kāi)發(fā)我們的Java相關(guān)項(xiàng)目,本文重點(diǎn)給大家介紹IDEA2022.2的簡(jiǎn)介、下載與安裝、初步配置,感興趣的朋友一起看看吧
    2022-11-11
  • springboot 接口返回字符串帶引號(hào)的問(wèn)題解決

    springboot 接口返回字符串帶引號(hào)的問(wèn)題解決

    本文主要介紹了springboot 接口返回字符串帶引號(hào)的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 解決java junit單元測(cè)試@Test報(bào)錯(cuò)的問(wèn)題

    解決java junit單元測(cè)試@Test報(bào)錯(cuò)的問(wèn)題

    今天小編就為大家分享一篇解決java junit單元測(cè)試@Test報(bào)錯(cuò)的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-11-11
  • Java如何通過(guò)反射獲取對(duì)象的屬性和值

    Java如何通過(guò)反射獲取對(duì)象的屬性和值

    這篇文章主要介紹了Java如何通過(guò)反射獲取對(duì)象的屬性和值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • Spring Properties的使用和配置方法

    Spring Properties的使用和配置方法

    這篇文章主要介紹了Spring Properties的使用和配置方法,本文不是原理分析、源碼分析文章,只是希望可以幫助讀者更好地理解和使用 Spring Properties,有興趣的可以了解一下
    2018-01-01
  • SpringCloud整合Netty集群實(shí)現(xiàn)WebSocket的示例代碼

    SpringCloud整合Netty集群實(shí)現(xiàn)WebSocket的示例代碼

    文章主要介紹了SpringCloud整合Netty集群實(shí)現(xiàn)WebSocket的相關(guān)內(nèi)容,包括服務(wù)注冊(cè)和發(fā)現(xiàn)中心的配置,如使用Nacos、CommandLineRunner啟動(dòng)Netty服務(wù)等,還介紹了通過(guò)Redis實(shí)現(xiàn)消息發(fā)布訂閱的機(jī)制,需要的朋友可以參考下
    2024-11-11
  • Java完整實(shí)現(xiàn)記事本代碼

    Java完整實(shí)現(xiàn)記事本代碼

    這篇文章主要介紹了Java實(shí)現(xiàn)的簡(jiǎn)易記事本,較為詳細(xì)的分析了基于java實(shí)現(xiàn)記事本程序的完整過(guò)程,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06

最新評(píng)論