在Spring框架中如何简化addAll方法的冗余代码实现?
优化方案
方案1:修复MapStruct继承字段识别问题(推荐)
你遇到的MapStruct无法识别父类字段的问题可以通过配置解决,不需要放弃MapStruct:
在你的NewsMapper接口上增加mappingInheritanceStrategy配置即可:
import org.mapstruct.Mapper; import org.mapstruct.MappingInheritanceStrategy; @Mapper(componentModel = "spring", mappingInheritanceStrategy = MappingInheritanceStrategy.AUTO_INHERIT_FROM_MAPPED_SUPERCLASS) public interface NewsMapper { News convertToEntity(NewsDto newsDto); }
配置完成后MapStruct会自动识别News父类中被@MappedSuperclass注解标记的字段,无需手动写映射规则。改造后的业务代码如下:
@Override public ApiResponse addAll(HttpHeaders headers, List<NewsDto> newsDtoList) { // 批量转换DTO到实体 List<News> newsList = Objects.requireNonNull(newsDtoList).stream() .map(newsMapper::convertToEntity) .toList(); // 批量保存,比循环单条save性能提升显著 newsRepo.saveAll(newsList); return new ApiResponse(true, "all list saved"); }
方案2:不用MapStruct的轻量实现
如果不想引入MapStruct,可以用Spring自带的BeanUtils配合空值忽略规则实现自动赋值,避免手写每一行判空赋值逻辑:
首先新增一个通用工具方法,用于获取对象中值为null的属性名:
import org.springframework.beans.BeanWrapper; import org.springframework.beans.BeanWrapperImpl; import java.util.HashSet; import java.util.Set; public class BeanUtilsExt { public static String[] getNullPropertyNames(Object source) { BeanWrapper src = new BeanWrapperImpl(source); Set<String> nullProps = new HashSet<>(); for (var pd : src.getPropertyDescriptors()) { if (src.getPropertyValue(pd.getName()) == null) { nullProps.add(pd.getName()); } } return nullProps.toArray(new String[0]); } }
改造后的业务代码:
@Override public ApiResponse addAll(HttpHeaders headers, List<NewsDto> newsDtoList) { List<News> newsList = Objects.requireNonNull(newsDtoList).stream() .map(newsDto -> { News news = new News(); // 复制属性时自动忽略null值,不会覆盖实体默认值 BeanUtils.copyProperties(newsDto, news, BeanUtilsExt.getNullPropertyNames(newsDto)); return news; }).toList(); newsRepo.saveAll(newsList); return new ApiResponse(true, "all list saved"); }
注意:如果NewsDto和News的对应字段名不一致,方案2无法自动映射,优先使用方案1即可。
内容的提问来源于stack exchange,提问作者Shoxrux Sindarov
相关产品推荐
相关产品推荐

