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

Spring框架下使用ModelMapper实现含OneToMany关联的Java实体类转DTO时仅保留关联对象ID的方案

解决ModelMapper映射OneToMany关系时仅保留关联实体ID列表的问题

我来帮你搞定这个问题——用ModelMapper把ClassA实体转换成只包含ClassB ID列表的DTO其实很简单,主要分两步:先定义对应的DTO类,然后配置ModelMapper的自定义映射规则就行。另外注意下你的ClassA代码里domains字段的类型是List<Domain>,但关联的实体是ClassB,这应该是笔误,我下面的示例会改成List<ClassB>来适配你的需求。

第一步:创建ClassADTO类

首先咱们得先定义好目标DTO,里面只保留需要的字段:ClassA的id,以及ClassB的ID列表:

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import java.util.List;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class ClassADTO {
    private Long id;
    // 只保留ClassB的ID列表
    private List<Long> domainIds;
}

第二步:配置ModelMapper的自定义映射

ModelMapper默认会尝试映射同名字段,但这里我们需要把List<ClassB>转换成List<Long>,所以得自定义映射规则。有两种常用方式:

方式一:使用PropertyMap自定义字段映射

这种方式更直观,直接指定字段之间的转换逻辑:

import org.modelmapper.ModelMapper;
import org.modelmapper.PropertyMap;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ModelMapperConfig {

    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();
        
        // 自定义ClassA到ClassADTO的映射规则
        modelMapper.addMappings(new PropertyMap<ClassA, ClassADTO>() {
            @Override
            protected void configure() {
                // 将ClassA的domains列表(List<ClassB>)转换为ClassB的id列表
                map().setDomainIds(source.getDomains().stream()
                        .map(ClassB::getId)
                        .toList());
            }
        });
        
        return modelMapper;
    }
}

方式二:使用Converter实现类型转换

如果这种列表转ID的场景在你的项目里比较通用,也可以定义一个通用的Converter:

import org.modelmapper.Converter;
import org.modelmapper.ModelMapper;
import org.modelmapper.spi.MappingContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.List;
import java.util.stream.Collectors;

@Configuration
public class ModelMapperConfig {

    @Bean
    public ModelMapper modelMapper() {
        ModelMapper modelMapper = new ModelMapper();
        
        // 定义List<ClassB>转List<Long>的转换器
        Converter<List<ClassB>, List<Long>> classBListToIdListConverter = new Converter<>() {
            @Override
            public List<Long> convert(MappingContext<List<ClassB>, List<Long>> context) {
                List<ClassB> source = context.getSource();
                if (source == null) {
                    return null;
                }
                return source.stream()
                        .map(ClassB::getId)
                        .collect(Collectors.toList());
            }
        };
        
        // 注册转换器,并指定字段映射
        modelMapper.addConverter(classBListToIdListConverter);
        modelMapper.typeMap(ClassA.class, ClassADTO.class)
                .addMapping(ClassA::getDomains, ClassADTO::setDomainIds);
        
        return modelMapper;
    }
}

第三步:在业务代码中使用

配置好之后,你就可以在Service或者Controller里注入ModelMapper,直接进行转换了:

import org.springframework.stereotype.Service;

@Service
public class ClassAService {

    private final ModelMapper modelMapper;
    // 假设你有ClassA的Repository
    private final ClassARepository classARepository;

    public ClassAService(ModelMapper modelMapper, ClassARepository classARepository) {
        this.modelMapper = modelMapper;
        this.classARepository = classARepository;
    }

    public ClassADTO getClassADtoById(Long id) {
        ClassA classA = classARepository.findById(id)
                .orElseThrow(() -> new RuntimeException("ClassA not found"));
        // 直接转换
        return modelMapper.map(classA, ClassADTO.class);
    }
}

这样转换后的ClassADTO返回给前端时,JSON格式就会是只包含id和domainIds列表的结构,完全符合你的需求~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 15:37:42