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

MapStruct不检测生成器中的设置程序

卢光誉
2023-03-14

这个问题和这个问题完全相似。这个问题没有一个公认的答案,我已经尝试了这个问题中的所有建议,但它们都不起作用。我不想尝试这个答案,因为我觉得它违背了我使用不可变表的目的。@marc-von-renteln在这里的评论中很好地总结了这个原因

我尝试了@Tobias-Schulte提供的答案。但这引起了一个不同的问题。在答案中的Mapper类中,试图从映射方法返回Immutable*.builder时会抛出一个错误,说找不到不可变类型。

我对MapStruct和Immutables记录的问题进行了详尽的搜索,但没有找到解决方案。不幸的是,使用MapStruct和Immutables组合的例子或人员几乎不多。mapstruct-examples存储库也没有使用不可变表的示例。

{
    "id": 0,
    "username": "TestUser",
    "email": "TestUser@demo.com",
    "userStatus": {
        "id": 1,
        "status": 1,
        "statusName": "Active"
    }

createUser:此处有问题http://localhost:8080/user/api/v1/users/create示例输入:

{
    "username": "TestUser",
    "email": "TestUser@demo.com",
    "userStatus": {
        "id": 1,
        "status": 1,
        "statusName": "Active"
    }
}

回应:

{
    "timestamp": "2019-04-28T09:29:24.933+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "Type definition error: [simple type, class com.immutablesmapstruct.demo.dto.model.ImmutableUserDto$Builder]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.immutablesmapstruct.demo.dto.model.ImmutableUserDto$Builder`, problem: Cannot build UserDto, some of required attributes are not set [username, email, userStatus]\n at [Source: (PushbackInputStream); line: 9, column: 1]",
    "path": "/user/api/v1/users/create"
}

以下是与问题相关的重要代码:

public class User {

    // Primary Key. Something that is annotated with @Id
    private int id;
    private String username;
    private String email;
    private UserStatus userStatus;

    private User(Builder builder) {
        id = builder.id;
        username = builder.username;
        email = builder.email;
        userStatus = builder.userStatus;
    }

    public static Builder builder() {
        return new Builder();
    }

    public int getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public String getEmail() {
        return email;
    }

    public UserStatus getUserStatus() {
        return userStatus;
    }

    public static final class Builder {
        private int id;
        private String username;
        private String email;
        private UserStatus userStatus;

        private Builder() {
        }

        public Builder setId(int id) {
            this.id = id;
            return this;
        }

        public Builder setUsername(String username) {
            this.username = username;
            return this;
        }

        public Builder setEmail(String email) {
            this.email = email;
            return this;
        }

        public Builder setUserStatus(UserStatus userStatus) {
            this.userStatus = userStatus;
            return this;
        }

        public User build() {
            return new User(this);
        }

package com.immutablesmapstruct.demo.dao.model;

/**
 * Status of user.
 * Example: Active or Inactive
 */
public class UserStatus {
    // Primary Key. Something that is annotated with @Id
    private int id;
    // A value of 1 or 0
    private int status;
    // Active , InActive
    private String statusName;

    private UserStatus(Builder builder) {
        id = builder.id;
        status = builder.status;
        statusName = builder.statusName;
    }

    public static Builder builder() {
        return new Builder();
    }

    public int getId() {
        return id;
    }

    public int getStatus() {
        return status;
    }

    public String getStatusName() {
        return statusName;
    }

    public static final class Builder {
        private int id;
        private int status;
        private String statusName;

        private Builder() {
        }

        public Builder setId(int id) {
            this.id = id;
            return this;
        }

        public Builder setStatus(int status) {
            this.status = status;
            return this;
        }

        public Builder setStatusName(String statusName) {
            this.statusName = statusName;
            return this;
        }

        public UserStatus build() {
            return new UserStatus(this);
        }
    }
}
package com.immutablesmapstruct.demo.dto.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.immutables.value.Value;

@Value.Immutable
@Value.Style(defaults = @Value.Immutable(copy = false), init = "set*")
@JsonSerialize(as = ImmutableUserDto.class)
@JsonDeserialize(builder = ImmutableUserDto.Builder.class)
public abstract class UserDto {

    @Value.Default
    @JsonProperty
    public int id() {
        return 0;
    }

    @JsonProperty
    public abstract String username();

    @JsonProperty
    public abstract String email();

    @JsonProperty
    public abstract UserStatusDto userStatus();

package com.immutablesmapstruct.demo.dto.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.immutables.value.Value;

@Value.Immutable
@Value.Style(defaults = @Value.Immutable(copy = false), init = "set*")
@JsonSerialize(as = ImmutableUserStatusDto.class)
@JsonDeserialize(builder = ImmutableUserStatusDto.Builder.class)
public abstract class UserStatusDto {

    @JsonProperty
    public abstract int id();

    @JsonProperty
    public abstract int status();

    @JsonProperty
    public abstract String statusName();

}
package com.immutablesmapstruct.demo.dto.mapper;

import com.immutablesmapstruct.demo.dao.model.User;
import com.immutablesmapstruct.demo.dao.model.UserStatus;
import com.immutablesmapstruct.demo.dto.model.UserDto;
import com.immutablesmapstruct.demo.dto.model.UserStatusDto;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

@Mapper(componentModel = "spring")
public interface UserMapper {

    UserMapper USER_MAPPER_INSTANCE = Mappers.getMapper(UserMapper.class);

    UserDto userDaoToDto(User user);

    //Problem here.
    User userDtoToDao(UserDto userDto);

    UserStatusDto userStatusDaoToDto(UserStatus userStatusDao);
    UserStatus userStatusDtoToDao(UserStatusDto userStatusDto);
}

package com.immutablesmapstruct.demo.dto.mapper;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2019-04-28T02:29:03-0700",
    comments = "version: 1.3.0.Final, compiler: javac, environment: Java 1.8.0_191 (Oracle Corporation)"
)
@Component
public class UserMapperImpl implements UserMapper {
...
...
    @Override
    public User userDtoToDao(UserDto userDto) {
        if ( userDto == null ) {
            return null;
        }

        com.immutablesmapstruct.demo.dao.model.User.Builder user = User.builder();

        return user.build();
    }
....
....
}

共有1个答案

令狐宏伟
2023-03-14

Mapstruct无法识别userdtouserstatusdto中的getter。

当您将这些抽象类中的现有方法(如公共抽象字符串username())更改为经典getter时,如

@JsonProperty("username")
public abstract String getUsername();

MapperImpl将包含所需的调用。注意,@jsonproperty之后需要有属性名称本身(因为方法名称已经更改)。

package com.immutablesmapstruct.demo.dto.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.immutables.value.Value;

@Value.Immutable
@Value.Style(defaults = @Value.Immutable(copy = false), init = "set*")
@JsonSerialize(as = ImmutableUserDto.class)
@JsonDeserialize(builder = ImmutableUserDto.Builder.class)
public abstract class UserDto {

    @Value.Default
    @JsonProperty("id")
    public int getId() {
        return 0;
    }

    @JsonProperty("username")
    public abstract String getUsername();

    @JsonProperty("email")
    public abstract String getEmail();

    @JsonProperty("userStatus")
    public abstract UserStatusDto getUserStatus();

}
package com.immutablesmapstruct.demo.dto.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.immutables.value.Value;

@Value.Immutable
@Value.Style(defaults = @Value.Immutable(copy = false), init = "set*")
@JsonSerialize(as = ImmutableUserStatusDto.class)
@JsonDeserialize(builder = ImmutableUserStatusDto.Builder.class)
public abstract class UserStatusDto {

    @JsonProperty("id")
    public abstract int getId();

    @JsonProperty("status")
    public abstract int getStatus();

    @JsonProperty("statusName")
    public abstract String getStatusName();

}

 类似资料:
  • 解决方案: 我不得不更改我的和的顺序。 我必须将放在之上,然后它就起作用了。 我将下面的pom更新到工作版本,所以这里没有非工作代码。 我还将lombok版本转换回当前版本,而不是使用edge版本。 原始问题: 我有2个或多或少相同的类集(见下面的示例) 一组是我的API的DTO,我希望它是不可变的,使用Lombok的@Value和@Builder 一组是要存储在数据库中的实体。使用Lombok的

  • MapStruct知道源状态检查,并且默认情况下使用状态检查器方法(如果存在的话)来验证目标对象中的字段是否应该使用源对象中的值更新。没有状态检查器,MapStruct默认只更新非空值的字段。 我想在REST控制器中使用DTO来使用MapStruct的source presence checknig实现部分更新策略,但是由于我使用Lombok来生成getter和setter,所以我还想生成sour

  • 如何在Map结构中完全禁用使用“构建器”?我根本不想使用它们,因为它们会给我带来各种各样的问题。 我在META-INF下创建了服务文件(我更喜欢一种将其分配给映射构建器=的方法,但我没有看到任何如何在代码中正确执行此操作的示例)。 它仍在尝试使用我想映射到的“ModifiableXXX”实例的不可变“构建器”实例。如果可用,我什至采取一种方法将其强制为可修改类型。 在另一个映射中,使用更新Modi

  • 当我在中使用时,它会生成一个,我希望能够访问该文件以在单元测试中导入,但intellij看不到它

  • 正如标题所述,我在src/test/java中有一个映射器接口,它不是由mapstruct处理器生成的。 在同一个项目中,生成中的所有映射器。这是预期的行为吗? 如何在测试源中生成映射器? 编辑(更多信息): 简化的Maven模块结构: root_project的pom.xml 的pom.xml基本为空:

  • 当使用“JSR330”componentModel使用MapStruct生成映射器实现时,micronaut将在运行时尝试注入这些实现时抛出一个NoSuchBeanException。 一个解决办法是使用提供程序来提供映射器对象,但生成的代码应该可以工作。 映射器定义: 控制器: pom.xml摘录: 当调用控制器上的方法时,我会期望Micronaut找到Mapstruct生成的类(它用@sing