SpringBoot中MapStruct实现实体关联到DTO的映射问题
MapStruct集合转ID数组映射解决方案
针对你的Animal实体转AnimalResponse DTO的需求,无需手动循环,MapStruct可以通过Java表达式或自定义可复用方法实现集合到ID数组的映射,同时处理其他关联属性的ID提取,具体实现如下:
方案一:使用@Mapping表达式直接转换
修改AnimalMapper接口,添加字段映射规则:
@Mapper public interface AnimalMapper extends BaseMapper<Animal, AnimalResponse> { AnimalMapper INSTANCE = Mappers.getMapper(AnimalMapper.class); @Override @Mapping(target = "animalTypes", expression = "java(animal.getAnimalTypes().stream().map(AnimalType::getId).toArray(Long[]::new))") @Mapping(target = "visitedLocations", expression = "java(animal.getVisitedLocations() != null ? animal.getVisitedLocations().stream().map(AnimalLocation::getId).toArray(Long[]::new) : null)") @Mapping(target = "chippedId", source = "chipperId.id") @Mapping(target = "chippingLocationId", source = "chippingLocationId.id") AnimalResponse toDto(Animal animal); }
说明:
animalTypes:通过Stream API遍历List<AnimalType>,提取每个对象的id并转为Long[]visitedLocations:增加空判断避免空指针异常,同样通过Stream提取id转数组chippedId/chippingLocationId:直接映射关联对象的id字段到DTO对应属性
方案二:自定义可复用的转换方法
如果需要复用集合转ID数组的逻辑,可以定义默认方法配合@Named注解:
// 定义通用ID提取接口(用于统一处理有getId()方法的对象) public interface HasId { Long getId(); } // 让AnimalType和AnimalLocation实现HasId接口 public class AnimalType implements HasId { // 原有代码,确保getId()方法存在 } public class AnimalLocation implements HasId { // 原有代码,确保getId()方法存在 } // 修改Mapper接口 @Mapper public interface AnimalMapper extends BaseMapper<Animal, AnimalResponse> { AnimalMapper INSTANCE = Mappers.getMapper(AnimalMapper.class); @Override @Mapping(target = "animalTypes", source = "animalTypes", qualifiedByName = "listToLongArray") @Mapping(target = "visitedLocations", source = "visitedLocations", qualifiedByName = "listToLongArray") @Mapping(target = "chippedId", source = "chipperId.id") @Mapping(target = "chippingLocationId", source = "chippingLocationId.id") AnimalResponse toDto(Animal animal); @Named("listToLongArray") default <T extends HasId> Long[] listToLongArray(List<T> list) { if (list == null) { return null; } return list.stream() .map(HasId::getId) .toArray(Long[]::new); } }
说明:
- 通用
HasId接口让所有带id的实体类实现,实现转换逻辑复用 @Named注解标记自定义转换方法,@Mapping中通过qualifiedByName指定使用该方法- 若不想定义接口,可单独为
AnimalType和AnimalLocation编写各自的转换方法,分别指定qualifiedByName
注意事项
- 确保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>
- 若
Account的id类型为Long,而DTO中chippedId是Integer,需在表达式中转换:java(animal.getChipperId().getId().intValue())
内容的提问来源于stack exchange,提问作者Hankie-2
相关产品推荐
相关产品推荐

