"Ambiguous constructors found" 使用 MapStruct 时存在多个构造函数时出错

"Ambiguous constructors found" error when there more than one constructor when using MapStruct

我是 mapstruct 的新手。我正在尝试将 ItemInfo 映射到 Item 对象,以下是我的 classes.

public class ItemInfo {

    private String itemOwner;
    private String itemOwnerArea;

    //getters and setters
}

以下是我打算转换为

的class
public class Item {
    private UserInfo owner;
    // getters and setters.
}

UserInfoclass(注意它有两个构造函数)

public class UserInfo {

    private final String username;
    private final String area;

    public UserInfo(String username, String area){
        //set 
    }

    public UserInfo(String info) {
        //set
    }

    // getters only
}

我创建了如下映射器界面

@Mapper
public interface ItemMapper {
    ItemMapper INSTANCE = Mappers.getMapper(ItemMapper.class);

    @Mapping(source = "itemOwner", target = "owner.username")
    @Mapping(source = "itemOwnerArea", target = "owner.area")
    Item mapItemInfoToItem(ItemInfo itemInfo);
}

当我构建它时,出现以下错误

 Ambiguous constructors found for creating com.app.test.UserInfo. Either declare parameterless 
constructor or annotate the default constructor with an annotation named @Default.

你能指导我吗?

更新。

正如@AnishB 所提到的,我添加了一个默认构造函数,但我得到了一个不同的错误

Property "username" has no write accessor in UserInfo for target name "owner.username".

谢谢

Mapstruct 的功能需要一个默认的空构造函数。

因此,更新 UserInfo class 以具有默认的空构造函数:

public class UserInfo {

    private final String username;
    private final String area;

    public UserInfo(){
        
    }

    public UserInfo(String username, String area){
        //set 
    }

    public UserInfo(String info) {
        //set
    }

    // setters and getters
}

或用 @Default 注释任何构造函数,以便mapstruct可以将该构造函数用作默认构造函数.

例如:

 @Default
 public UserInfo(String info) {
    //set
 }

此外,您还必须在 UserInfo 中添加设置器。

这是文档:https://github.com/mapstruct/mapstruct/blob/master/documentation/src/main/asciidoc/chapter-3-defining-a-mapper.asciidoc#using-constructors

使用@Default注解标记默认构造函数。

我们正在努力改进此处的错误消息。

来自当前错误信息

Ambiguous constructors found for creating com.app.test.UserInfo. Either declare parameterless constructor or annotate the default constructor with an annotation named @Default.

您有 2 个选择:

  • 创建一个空的构造函数,MapStruct 将使用它。然而,这不是必需的,我强烈建议不要使用它。
  • 创建您自己的 @Default 注释并注释 MapStruct 应使用的默认构造函数。我强烈推荐这种方法。

MapStruct 不提供此注释,因为它专注于 bean 映射并且不想使用来自 MapStruct 的注释污染实体代码。 因此它可以使用来自任何包的任何 Default 注释。

例如

package foo.support.mapstruct;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.CONSTRUCTOR)
@Retention(RetentionPolicy.CLASS)
public @interface Default {
}

您已经这样做了,下一条错误消息:

Property "username" has no write accessor in UserInfo for target name "owner.username".

是不是说用户名没有写访问器,因为很可能你已经注释了单参数构造函数。如果你这样做了,那么 MapStruct 只知道 area 而不知道 username。该错误的另一种选择是您添加了一个空的无参数构造函数并且没有设置器。

您很可能需要

@Default
public UserInfo(String username, String area){
    //set 
}