具有多个参数的MapStruct QualifiedByName

时间:2017-12-07 11:50:56

标签: java intellij-idea java-8 mapstruct

我遇到过一种情况,我的映射方法有3个参数,所有这三个参数都用于导出目标类型的一个属性。

我在接口中创建了一个默认的映射方法,保留了导出属性的逻辑,现在为了调用这个方法,我可以在expression = "java( /*method call here*/ )"注释中使用@Mapping

有没有办法用@qualifiedByName之类的任何一个maptruct注释来做这个,我试着用注释具有表达式属性的注释并使用qualifiedByName,但它不起作用:

@Mapper
public interface OneMapper {

    @Mapping(target="id", source="one.id")
    //@Mapping(target="qualified",expression = "java( checkQualified (one, projId, code) )")
    @Mapping(target="qualified",qualifiedByName="checkQualifiedNamed")
    OneDto createOne (One one, Integer projId, Integer val, String code);

    @Named("checkQualifiedNamed")
    default Boolean checkQualified (One one, Integer projId, Integer val, String code) {
        if(one.getProjectId() == projId && one.getVal() == val && one.getCode().equalsIgnoreCase(code)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;                   
    }
}

3 个答案:

答案 0 :(得分:4)

目前,MapStruct不支持具有多个源属性的映射方法。

但是,在您的情况下,您可以使用1.2.0中的@Context。根据我的理解,projIdcode只是映射的帮助器,它们不用于映射目标属性。

所以你可以做一些事情(它应该在理论上起作用):

@Mapper
public interface OneMapper {

    @Mapping(target="id", source="one.id")
    @Mapping(target="qualified", qualifiedByName="checkQualifiedNamed")
    OneDto createOne (One one, @Context Integer projId, @Context String code);

    @Named("checkQualifiedNamed")
    default Boolean checkQualified (One one, @Context Integer projId, @Context String code) {
        if(one.getProjectId() == projId && one.getCode().equalsIgnoreCase(code)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;                   
    }
}

另一种选择是将所有这些属性提取到一个单独的类中并传递它(这将允许多个相同类型的参数)。

该课程如下:

public class Filter {

    private final Integer projId;
    private final Integer val;
    private final String code;

    public Filter (Integer projId, Integer val, String code) {
        this.projId = projId;
        this.val = val;
        this.code = code;
    }

    //getters
}

您的映射器将如下所示:

@Mapper
public interface OneMapper {

    @Mapping(target="id", source="one.id")
    @Mapping(target="qualified", qualifiedByName="checkQualifiedNamed")
    OneDto createOne (One one, @Context Filter filter);

    @Named("checkQualifiedNamed")
    default Boolean checkQualified (One one, @Context Filter filter) {
        if(one.getProjectId() == filter.getProjId() && one.getVal() == filter.getVal() && one.getCode().equalsIgnoreCase(filter.getCode())) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;                   
    }
}

然后,您可以调用映射器,如:mapper.createOne(one, new Filter(projId, val, code));

答案 1 :(得分:1)

从1.2版开始支持: http://mapstruct.org/documentation/stable/reference/html/#mappings-with-several-source-parameters

例如这样的例子:

@Mappings({
  @Mapping(source = "person.description", target = "description"),
  @Mapping(source = "address.houseNo", target = "houseNumber")
})
DeliveryAddressDto personAndAddressToDeliveryAddressDto(Person person, Address address);

答案 2 :(得分:0)

您可以创建一个默认方法,该方法使用其他上下文参数在内部调用mapstruct方法。这样,您就可以在'qualifiedByName'部分获取所有参数

@Mapper
public interface OneMapper {

    default OneDto createOne(One one, Integer projId, Integer val, String code) {
        return createOneWithContext(one,porjId,val,code
                                    one,porjId,val,code //as context params
        );
    }

    @Mapping(target="id", source="one.id")
    @Mapping(target="qualified",source="one",qualifiedByName="checkQualifiedNamed")
    OneDto createOneWithContext (One one, Integer projId, Integer val, String code
                     @Context One oneAsContext, 
                     @Context Integer projIdAsContext, 
                     @Context Integer valAsContext, 
                     @Context String codeAsContext
    
);

    @Named("checkQualifiedNamed")
    default Boolean checkQualified (One one, @Context Integer projId, @Context Integer val, @Context String code) {
        if(one.getProjectId() == projId && one.getVal() == val && one.getCode().equalsIgnoreCase(code)) {
            return Boolean.TRUE;
        }
    return Boolean.FALSE;                   
    }
}



```