无法使用MapStruct映射嵌套@Data

问题描述 投票:0回答:3

尝试使用 @Data 和 @Builder 映射嵌套对象时,mapStruct 抛出以下错误:“在目标类型中找不到属性“profile”的读取访问器。”

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

  // only for testing mapping is working
  @Mapping(target = "profile.organization", source = "organization")
  RequestCreateOktaUser toEntity(Integer organization);

  // only for testing mapping is working
  @Mapping(target = "profile.login", source = "request.profile.email")
  RequestCreateOktaUser toEntity(RequestMobilePreRegisterLocation.User request);
  
  // Throw error "No read accessor found for property "profile" in target type" at compile time
  @Mapping(target = "profile.organization", source = "organization")
  @Mapping(target = "profile.login", source = "request.profile.email")
  RequestCreateOktaUser toEntity(RequestMobilePreRegisterLocation.User request, Integer organization);

}

为了简单起见,使用 Lombok 简化模型

@Data
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
public class RequestCreateOktaUser {

  private Profile profile;

  @Data
  @NoArgsConstructor
  @AllArgsConstructor(access = AccessLevel.PRIVATE)
  @Builder
  public static class Profile {
    private String login;
    private String email;
    private Integer organization;
  }

}
@Data
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Builder
public class RequestMobilePreRegisterUser {

  @Valid
  private User user;


  @Data
  @NoArgsConstructor
  @AllArgsConstructor(access = AccessLevel.PRIVATE)
  @Builder
  public static class User {

    @Valid
    private Profile profile;

    @Data
    @NoArgsConstructor
    @AllArgsConstructor(access = AccessLevel.PRIVATE)
    @Builder
    public static class Profile {

      @NotEmpty
      @Email
      private String email;

    }

}

前两个映射按预期工作,但是当尝试组合这两个映射时,会在编译时抛出以下错误“在目标类型中找不到属性“配置文件”的读取访问器。”

如果有人能在这方面帮助我,我将非常感激。

非常感谢,

乔纳森。

spring-boot lombok mapstruct
3个回答
28
投票

解决方案:

@Mapper(componentModel = "spring", builder = @Builder(disableBuilder = true))

1
投票

我们可以添加另一个映射器,而不是忽略构建器,例如

ProfileMapper
,然后在“父映射器”(例如
UserMapper
)中,您可以使用这样的映射器注释

@Mapper(uses = {ProfileMapper.class})
interface UserMapper {
...
}

0
投票

最好的办法是避免嵌套映射。 您可能有单独的嵌套映射方法。所以你可以有一个方法来首先转换嵌套类型。例如用户配置文件。 然后你可以使用

expression
让mapstruct知道它使用哪种方法进行嵌套映射(即使需要也不确定)

如果您还有其他内容要映射到配置文件(例如组织),而这些内容不属于嵌套源,则可以使用

@AfterMapping

© www.soinside.com 2019 - 2024. All rights reserved.