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
相关产品推荐
相关产品推荐

