Spring Boot中如何用MapStruct限制List映射的最大返回条目数?
问题:MapStruct映射时限制集合返回条数(最多2条)
在Spring Boot项目中使用MapStruct做对象映射,现有如下Mapper代码:
@Mapper(componentModel = "spring", uses = { PubMapper.class, IsbnMapper.class}) public interface DepotMapper { @Mapping(target = "idDepot", source = "depot.idDepot") @Mapping(target = "isbns", source = "pub.isbns") DepositPub entityToDto(Depot depot); } @Mapper(componentModel = "spring") public interface IsbnIssnMapper { @Named("isbnToDto") IsbnRecord isbnToDto(Isbn isbn); @IterableMapping(qualifiedByName = "isbnToDto") List<IsbnRecord> isbnRecordMap(List<Isbn> isbns); }
调用DepotMapper.entityToDto()方法时,希望映射后的DepositPub.isbns最多只包含2条IsbnRecord记录,但MapStruct本身没有直接的配置选项支持这种条数限制,求可行的解决办法。
解决方案
方法1:在IsbnIssnMapper中新增带条数限制的映射方法
直接在负责ISBN映射的Mapper里添加支持条数限制的默认方法,然后在DepotMapper中指定使用该方法:
@Mapper(componentModel = "spring") public interface IsbnIssnMapper { @Named("isbnToDto") IsbnRecord isbnToDto(Isbn isbn); @IterableMapping(qualifiedByName = "isbnToDto") List<IsbnRecord> isbnRecordMap(List<Isbn> isbns); // 新增带条数限制的映射方法 @Named("isbnToDtoWithLimit") default List<IsbnRecord> isbnRecordMapWithLimit(List<Isbn> isbns) { if (isbns == null) { return null; } // 截取前2条,不足2条则返回全部 return isbns.stream() .limit(2) .map(this::isbnToDto) .collect(Collectors.toList()); } }
修改DepotMapper的映射配置,指定使用这个带限制的方法:
@Mapper(componentModel = "spring", uses = { PubMapper.class, IsbnIssnMapper.class}) public interface DepotMapper { @Mapping(target = "idDepot", source = "depot.idDepot") @Mapping(target = "isbns", source = "pub.isbns", qualifiedByName = "isbnToDtoWithLimit") DepositPub entityToDto(Depot depot); }
方法2:在DepotMapper中添加默认处理方法
如果不想改动IsbnIssnMapper,可以在DepotMapper里定义默认方法,手动完成映射和条数限制:
@Mapper(componentModel = "spring", uses = { PubMapper.class, IsbnIssnMapper.class}) public interface DepotMapper { IsbnIssnMapper ISBN_MAPPER = Mappers.getMapper(IsbnIssnMapper.class); @Mapping(target = "idDepot", source = "depot.idDepot") @Mapping(target = "isbns", ignore = true) // 忽略自动映射,手动处理 DepositPub entityToDto(Depot depot); // 重载方法,手动处理ISBN集合的映射和条数限制 default DepositPub entityToDtoWithIsbnLimit(Depot depot) { DepositPub dto = entityToDto(depot); List<Isbn> isbns = depot.getPub().getIsbns(); if (isbns != null) { List<IsbnRecord> limitedIsbns = isbns.stream() .limit(2) .map(ISBN_MAPPER::isbnToDto) .collect(Collectors.toList()); dto.setIsbns(limitedIsbns); } return dto; } }
之后直接调用entityToDtoWithIsbnLimit()方法即可得到符合要求的结果。
方法3:使用@AfterMapping注解做后置处理
利用MapStruct的@AfterMapping注解,在映射完成后对集合进行截取,不需要修改原有映射逻辑:
@Mapper(componentModel = "spring", uses = { PubMapper.class, IsbnIssnMapper.class}) public interface DepotMapper { @Mapping(target = "idDepot", source = "depot.idDepot") @Mapping(target = "isbns", source = "pub.isbns") DepositPub entityToDto(Depot depot); // 映射完成后处理ISBN条数限制 @AfterMapping default void limitIsbnCount(@MappingTarget DepositPub dto) { List<IsbnRecord> isbns = dto.getIsbns(); if (isbns != null && isbns.size() > 2) { dto.setIsbns(isbns.subList(0, 2)); } } }
这种方式对原有代码侵入性最小,适合需要保留原有方法签名的场景。
内容的提问来源于stack exchange,提问作者robert trudel
相关产品推荐
相关产品推荐

