You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从含List型DTO的BookingEntity映射数据至ViewAllDTO?

解决MongoDB BookingEntity到ViewAllDTO的List类型字段映射问题

问题分析

你的代码编译错误核心原因是直接把List类型字段当成单个对象访问:

  • BookingEntity的booking是List<BookingDTO>,没有getBooking_number()方法,需从List元素中提取booking_number
  • shipper_details是List<ShipperDetailsDTO>,没有getFirst_name()/getLast_name()方法,需从List元素中获取字段拼接
  • item是List<ItemDTO>,无法直接将多个字段参数传给setItem_details(),需先把ItemDTO字段整合为字符串

基础解决方案(手动映射)

假设每个BookingEntity对应单个BookingDTO、ShipperDetailsDTO(若需处理多元素场景,可根据业务逻辑调整,比如拼接所有元素或取指定元素),修正后的映射方法如下:

import org.apache.commons.lang3.StringUtils;
import java.util.Optional;

public ViewAllDTO toDTO(BookingEntity entity) {
    ViewAllDTO dto = new ViewAllDTO();

    // 提取booking_number:空值安全处理List,取第一个元素的booking_number
    Optional.ofNullable(entity.getBooking())
            .filter(list -> !list.isEmpty())
            .map(list -> list.get(0).getBooking_number())
            .ifPresent(dto::setBooking_number);

    // 拼接sender_name:空值安全处理List,拼接first_name+last_name
    Optional.ofNullable(entity.getShipper_details())
            .filter(list -> !list.isEmpty())
            .map(list -> list.get(0))
            .map(shipper -> StringUtils.normalizeSpace(String.format("%s %s", shipper.getFirst_name(), shipper.getLast_name())))
            .ifPresent(dto::setSender_name);

    // 整合item_details:循环拼接所有ItemDTO的字段为字符串
    StringBuilder itemDetailsBuilder = new StringBuilder();
    Optional.ofNullable(entity.getItem())
            .ifPresent(items -> {
                for (ItemDTO item : items) {
                    itemDetailsBuilder.append(String.format(
                            "商品描述:%s,重量:%s,尺寸:%sx%sx%s,申报价值:%s,包装类型:%s\n",
                            item.getItem_description(),
                            item.getWeight(),
                            item.getHeight(), item.getLength(), item.getWidth(),
                            item.getDeclared_value(),
                            item.getPackage_handling_type()
                    ));
                }
            });
    dto.setItem_details(itemDetailsBuilder.toString().trim());

    return dto;
}

关键处理点说明

  1. 空值安全:用Optional处理List为null或空的情况,避免空指针异常
  2. List元素提取:通过filter(list -> !list.isEmpty())确保List有元素后再操作,若需支持多元素,可改为拼接所有值(比如String.join(",", list.stream().map(BookingDTO::getBooking_number).toList()))
  3. 字段拼接:item_details用StringBuilder循环拼接,格式可根据业务需求调整(比如改为JSON格式字符串)

进阶方案:用MapStruct简化映射

若项目有大量映射需求,推荐用MapStruct框架自动生成映射代码,减少手动编写重复逻辑。

1. 添加MapStruct依赖(Maven)

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

2. 定义Mapper接口

import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import java.util.List;
import java.util.Optional;

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

    @Mapping(source = "booking", target = "booking_number", qualifiedByName = "extractBookingNumber")
    @Mapping(source = "shipper_details", target = "sender_name", qualifiedByName = "buildSenderName")
    @Mapping(source = "item", target = "item_details", qualifiedByName = "buildItemDetails")
    ViewAllDTO toViewAllDTO(BookingEntity entity);

    @Named("extractBookingNumber")
    default String extractBookingNumber(List<BookingDTO> bookingList) {
        return Optional.ofNullable(bookingList)
                .filter(list -> !list.isEmpty())
                .map(list -> list.get(0).getBooking_number())
                .orElse(null);
    }

    @Named("buildSenderName")
    default String buildSenderName(List<ShipperDetailsDTO> shipperList) {
        return Optional.ofNullable(shipperList)
                .filter(list -> !list.isEmpty())
                .map(list -> list.get(0))
                .map(shipper -> StringUtils.normalizeSpace(String.format("%s %s", shipper.getFirst_name(), shipper.getLast_name())))
                .orElse(null);
    }

    @Named("buildItemDetails")
    default String buildItemDetails(List<ItemDTO> itemList) {
        if (itemList == null || itemList.isEmpty()) {
            return "";
        }
        StringBuilder builder = new StringBuilder();
        for (ItemDTO item : itemList) {
            builder.append(String.format(
                    "商品描述:%s,重量:%s,尺寸:%sx%sx%s,申报价值:%s,包装类型:%s\n",
                    item.getItem_description(),
                    item.getWeight(),
                    item.getHeight(), item.getLength(), item.getWidth(),
                    item.getDeclared_value(),
                    item.getPackage_handling_type()
            ));
        }
        return builder.toString().trim();
    }
}

3. 使用Mapper

在业务类中注入BookingMapper即可直接调用:

@Autowired
private BookingMapper bookingMapper;

public ViewAllDTO convertToViewAllDTO(BookingEntity entity) {
    return bookingMapper.toViewAllDTO(entity);
}

注意事项

  • 若List字段包含多个元素,需根据业务需求调整逻辑:比如拼接所有值、取最新元素或指定元素
  • 空值处理是生产环境必备,避免出现空指针异常
  • item_details的拼接格式可根据前端需求调整,比如改为JSON格式字符串

内容的提问来源于stack exchange,提问作者Practice Tech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 14:54:57