将实体List映射为DTO List时如何通过表达式或自定义方法指定DTO属性映射规则
实现方案
MapStruct本身原生支持集合映射方法自动复用对应单元素映射的所有逻辑,你只需要调整列表映射方法的入参即可:
具体修改步骤
- 第一步:给列表映射方法补充
userId入参,和单元素映射方法的第二个参数保持一致 - 第二步:删除列表映射方法上的
@Mapping注解,集合映射不需要单独配置字段映射,会自动继承单元素方法的所有映射规则
修改后的代码如下:
@Mapping(target = "courseId", source = "resource.course.id") @Mapping(target = "favoured", expression = "java(isResourceFavoured(resource, userId))") public abstract ResourceDto resourceToResourceDto(Resource resource, Long userId); // 不需要加任何@Mapping注解,自动调用上面的单元素映射方法 public abstract List<ResourceDto> resourceToResourceDto(List<Resource> resources, Long userId); public boolean isResourceFavoured(Resource resource, Long userId) { ApplicationUser user = userService.findApplicationUserById(userId); return resourceService.isFavoured(resource, user); }
实现原理
MapStruct生成集合映射的实现代码时,会自动匹配当前Mapper中类型对应的单元素映射方法:当存在入参类型为Resource+Long、返回值为ResourceDto的方法时,集合方法会自动遍历所有元素,逐个调用该单元素方法完成转换,单元素方法上配置的字段映射规则、自定义表达式、自定义映射方法都会被完整复用,不需要额外配置。
生成的集合方法实现逻辑大致如下:
@Override public List<ResourceDto> resourceToResourceDto(List<Resource> resources, Long userId) { if (resources == null) { return null; } List<ResourceDto> dtoList = new ArrayList<>(resources.size()); for (Resource resource : resources) { // 直接调用你定义的单元素映射方法,所有逻辑都复用 dtoList.add(resourceToResourceDto(resource, userId)); } return dtoList; }
原有代码问题说明
你之前给列表方法加的@Mapping(target = "courseId", source = "course.id")是无效的,因为集合类型List<Resource>本身不存在course属性,编译时会提示字段找不到错误,直接删除即可。
内容的提问来源于stack exchange,提问作者josef
相关产品推荐
相关产品推荐

