当前位置: 首页 > 知识库问答 >
问题:

带有多个参数的MapStruct QualifiedByName

钱志义
2023-03-14

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

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

有没有什么方法可以在mapstruct注释中做到这一点,比如@qualifiedByName,我试着用expression属性和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个答案

狄信然
2023-03-14

如果需要基于来自同一源对象的多个源字段计算单个目标字段,可以将完整的源对象传递给自定义映射器函数,而不是单个字段:

示例实体:

@Entity
@Data
public class User {
    private String firstName;
    private String lastName;
}

DTO示例


public class UserDto {
    private String fullName;
}

... 还有地图绘制者。。。而不是传递单个源(名字):

@Mapper
public abstract class UserMapper {

    @Mapping(source = "firstName", target = "fullName", qualifiedByName = "nameTofullName")
    public abstract UserDto userEntityToUserDto(UserEntity userEntity);


    @Named("nameToFullName")
    public String nameToFullName(String firstName) {
        return String.format("%s HOW DO I GET THE LAST NAME HERE?", firstName);
    }

... 将完整实体对象(userEntity)作为源传递:

@Mapper
public abstract class UserMapper {

    @Mapping(source = "userEntity", target = "fullName", qualifiedByName = "nameToFullName")
    public abstract UserDto userEntityToUserDto(UserEntity userEntity);


    @Named("nameToFullName")
    public String nameToOwner(UserEntity userEntity) {
        return String.format("%s %s", userEntity.getFirstName(), userEntity.getLastName());
    }
蒋寒
2023-03-14

自1.2版起,支持:http://mapstruct.org/documentation/stable/reference/html/#mappings-有几个源参数

例如:

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

使现代化

由于Mapstruct允许将多个源参数映射到单个目标中,因此我建议从映射器中提取checkQualified方法,而是提前计算结果,并使用checkQualified方法的结果调用映射器。Mapstruct是一个映射库,不擅长执行任意逻辑。这不是不可能的,但就我个人而言,我看不出它在你的特殊情况下增加了什么价值。

使用提取的逻辑,您的映射器可以看起来像这样:

@Mapper
public interface OneMapper {
    OneDto toOneDto(One one, Boolean qualified);
}

映射器可以这样使用:

One one = new One(1, 10, 100, "one");
boolean qualified = checkQualified(one, 10, 100, "one");
boolean notQualified = checkQualified(one, 10, 100, "two");
OneDto oneDto = mapper.toOneDto(one, isQualified);

有关完整示例,请参见:https://github.com/phazebroek/so-mapstruct/blob/master/src/main/java/nl/phazebroek/so/MapStructDemo.java

淳于俊迈
2023-03-14

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

然而,在您的情况下,您可以使用1.2.0中的@Context。据我所知,项目ID和code只是映射的助手,它们不用于映射目标属性。

所以你可以这样做(理论上应该可行):

@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(一个,新过滤器(projId、val、code))

 类似资料:
  • 我是Node.js和Express的新手,我一直在做一个RESTful API项目,我试图在URL中发送一个带有多个参数的GET请求: 这是我的路线: 我是这样称呼它的: 而且我也尝试过 它最终会走这条路线: 那么,我写endpoint的方式是否错误?还是我要求的方式?

  • 问题内容: 我知道关于从Java执行流程有很多解决的问题,但是我无法使用提供的答案解决问题。我正在尝试从Java应用程序创建postgresql数据库备份。我使用以下代码 执行以上代码后,出现以下错误: 仅当备份文件的路径包含空格时才出现问题,否则将创建备份。我试图在文件路径中同时使用斜杠和反斜杠,但我引用了文件路径,但每次都遇到相同的错误。可以从命令提示符处执行命令。 我做错了。关于Proces

  • 问题内容: 根据文档,可以为该标志定义多个args ,但我不知道如何。我尝试了以下方法: =>这将返回错误。 我也尝试过: =>这会将一个变量设置为值“ 5,number_of_replicas = 2” 知道如何定义多个参数吗? 问题答案: 与每个参数一起使用。 如果您要传递两个参数,则在每个参数中添加:

  • 问题内容: 在Go模板中,有时将正确的数据传递到正确的模板的方式令我感到尴尬。用流水线参数调用模板看起来就像只用一个参数调用函数。 假设我有一个Gophers网站,有关Gophers。它具有一个主页主模板和一个用于打印Gophers列表的实用程序模板。 http://play.golang.org/p/Jivy_WPh16 输出: 现在,我想在子模板中添加一些上下文:在列表内以不同的方式设置名称“

  • 问题内容: 使用jinja2 url_for()功能时出现问题。 我有一条这样的路线: 在jinja模板文件中,我想创建一个链接到article_page的URL,所以我这样写: 但是当我运行此页面时,出现错误: 似乎缺少第二个参数。如何正确使用多个参数? 问题答案: 根据文件: 如果查询参数的值为“无”,则将跳过整个对。 确保不是。 或在函数中指定默认值。

  • 问题内容: 我有一个源输入 input.txt 我想将这些输入馈入程序,如下所示: 所以我尝试使用 xargs ,但是没有运气。 它给 但我想要 任何的想法? 问题答案: 到目前为止给出的解决方案都无法正确处理包含空格的文件名。如果文件名包含“或”,有些甚至会失败。如果输入文件是由用户生成的,则应该准备好使用令人惊讶的文件名。 GNU Parallel 很好地处理了这些文件名,并为您(至少)提供了