使用 mapstruct 如何使用 spring 组件映射器将对象映射到对象列表

using mapstruct how to map an object to a list of objects with spring component mappers

我正在尝试将对象 A 映射到对象 B 的列表。 我有一个从对象 A 映射到对象 B 的映射器。

例如,我尝试了多种不同的方式 尝试使用 'expressions' 创建包含一个对象 A 的列表 'qualifiedByName' 但这行不通,因为我认为 当你使用 expressions/qualifiedByName 时你不能使用 自定义映射器(我在这里可能是错的?)

我还尝试使用 @aftermapper 方法调用映射器 获取目标映射器句柄的“mappers.getMapper” 但是我发现映射器中使用的 spring beans 没有人口的地方。 aftermapping 中的映射使得 感觉我可以用源代码调用目标映射器 然后将目标添加到列表中。所以我希望那里 是从我的映射器获取映射器组件句柄的另一种方法。

我所有的映射器都使用 @Mapper(componentModel="spring",

欢迎所有建议 下面是显示问题的代码示例。

此致, 德克兰

    // SPECIESTOLOGSPECY.JAVA
    // From this mapper I want to call SpecyToLogDeclarationMapperApi mapper
    // to map ‘species’ to ‘logdeclarations’ which is a list of logdeclaration
    // you can see want I am trying to do in the aftermapping method
    // where I map species to logdeclaration and then put this into a list
    // unfortunately I need other mapping components (ConfigMapperFromCode & SpecyToFishDeclarationMapperApi)
    // to be autowired into  SpecyToLogDeclarationMapperApi and this is not happening.
    // is there another way to get a handle to the spring managed 
    // SpecyToLogDeclarationMapperApi mapper ?

     @Mapper(componentModel="spring",
     uses = {
         ConfigMapperFromCode.class, 
         GeoInfoMapper.class,
         SpecyToLogDeclarationMapperApi.class
            })
     public interface SpeciesToLogSpecy {
     SpecyToLogDeclarationMapperApi MAPPER = Mappers.getMapper(SpecyToLogDeclarationMapperApi.class);

@Mappings(
        {
            @Mapping(target="createdate", expression = "java(java.sql.Timestamp.valueOf(java.time.LocalDateTime.now()))"),
            @Mapping(target="speciesid", qualifiedByName={"ConfigMapperFromCode", "speciesIdFromCodeAsDecimal"},  source = "species.speciesCode"),
            @Mapping(target="unitweight", constant = "1"),
            @Mapping(target = "inactiveind", constant = "N"),
            @Mapping(target = "unitdefaultind", constant = "Y"),
            @Mapping(target = "sectiontypeid", expression = "java(new BigDecimal(ie.gov.agriculture.fisheries.logsheet.mapping.constants.MappingConstants.LOG_SPECIES_SECTION_TYPE_SHEETDECLARATION))"),
            @Mapping(target = "unituomid", expression = "java(new BigDecimal(ie.gov.agriculture.fisheries.logsheet.mapping.constants.MappingConstants.LOGSHEET_CATCHUNITS_KG))"),
            @Mapping(target="catchtypeid",  qualifiedByName={"ConfigMapperFromCode", "returnCatchTypeId"},  source = "species.spType"),
            @Mapping(target="legalfishsizetypeid",  qualifiedByName={"ConfigMapperFromCode", "legalFishSizeTypeIdFromCode"},  source = "species.fishSizeClass"),
            @Mapping(target="presenttypeid",  qualifiedByName={"ConfigMapperFromCode", "presentationTypeIdFromCode"},  source = "species.presentation.presentationType"),
            //@Mapping(target="logdeclarations", source = "species")                
        }           
         )
Logspecy speciesToLogspecy(Species species, @Context ExtraFields extraFields);


    @AfterMapping
    default void afterMap(@MappingTarget Logspecy logspecy, @Context ExtraFields extraFields){
    Logdeclaration logDeclaration = MAPPER.SpeciesToLogDeclarations(species, extraFields);

    List<Logdeclaration> logdeclarations = new ArrayList<Logdeclaration>(); 
    logdeclarations.add(logDeclaration);
    logSpecy.setLogdeclarations(logdeclarations);    
    {




    // SPECYTOLOGDECLARATIONMAPPERAPI.JAVA



    @Mapper(componentModel="spring",
    uses = {
        ConfigMapperFromCode.class,
        SpecyToFishDeclarationMapperApi.class       
        }    
)
public interface SpecyToLogDeclarationMapperApi {


@Mappings(
        {
            @Mapping(target="createdate", expression = "java(java.sql.Timestamp.valueOf(java.time.LocalDateTime.now()))"),              
            @Mapping(target="geartypeid", qualifiedByName={"ConfigMapperFromCode", "gearIdFromCode"},  source = "species.gearType"),
            @Mapping(target="fishcount", source = "species.qty"),
            @Mapping(target = "inactiveind", constant = "N"),
            @Mapping(target="packagetypeid", qualifiedByName={"ConfigMapperFromCode", "packagingTypeIdFromCode"},  source = "species.presentation.packaging"),
            @Mapping(target="packagecount", source = "species.presentation.pkgunit"),
            @Mapping(target="avgpackageweight", source = "species.presentation.pkgUnitWeight"),
            @Mapping(target="conversionfactor", source = "species.presentation.convFactor"),
            @Mapping(target="fishdeclaration", source = "species.geoInfo")              
        }           
        )
Logdeclaration SpeciesToLogDeclarations (Species species, @Context ExtraFields extraFields);    

问题是您正在尝试将 Species 映射到 List<Logdeclaration>,而 MapStruct 找不到这样的映射方法。为了使其工作,您可以将以下方法添加到您的 SpecyToLogDeclarationMapperApi:

default List<Logdeclaration> SpeciesToLogDeclarationsToList(Species species, @Context ExtraFields extraFields) {
    if ( species == null ) {
        return null;
    }

    Logdeclaration logDeclaration = SpeciesToLogDeclarations(species, extraFields);

    List<Logdeclaration> logdeclarations = new ArrayList<Logdeclaration>();
    logdeclarations.add(logDeclaration);
    return logdeclarations;
}

这是一些额外的东西,我认为你可以做这些来改进你的代码并使用 MapStruct "more correctly":

  • 当组件模型不是 default
  • 时,您需要删除 Mappers#getMapper(Class) 的用法
  • 如果您不想在表达式中使用 FQN,可以使用 Mapper#imports,MapStruct 将在实现中导入它们。
  • 当您只有一个源参数时,您不必在映射中使用它的名称

例如

@Mapping(target="fishcount", source = "species.qty")

可以是

@Mapping(target="fishcount", source = "qty")