【问题标题】:How can I use Java records as DTO with ModelMapper?如何将 Java 记录用作 ModelMapper 的 DTO?
【发布时间】:2020-06-18 17:07:19
【问题描述】:

我正在重构我的代码。我想在我的 DTO 中使用 java 记录而不是 java 类。要将 DTO 转换为实体,我使用的是 ModelMapper(版本 2.3.5)。当我尝试获取有关用户的信息(调用方法将实体转换为 DTO)时,我收到此错误。

Failed to instantiate instance of destination xxx.UserDto. Ensure that xxx.UserDto has a non-private no-argument constructor.

这是我的代码。

public record UserDto(String firstName,
                      String lastName,
                      String email,
                      String imageUrl) {}

@RestController
public class UserController {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ModelMapper modelMapper;


    @GetMapping("/user/me")
    @PreAuthorize("hasRole('USER')")
    public UserDto getCurrentUser(@CurrentUser UserPrincipal userPrincipal) {
        return convertToDto(userRepository.findById(userPrincipal.getId())
                .orElseThrow(() -> new ResourceNotFoundException("User", "id", userPrincipal.getId())));
    }


    private UserDto convertToDto(User user) {
        UserDto userDto = modelMapper.map(user, UserDto.class);
        return userDto;
    }

    private User convertToEntity(UserDto userDto) throws Exception {
        User post = modelMapper.map(userDto, User.class);
        return post;
    }
}

编辑:更新到版本 2.3.8 没有帮助!

【问题讨论】:

  • 您可以尝试使用2.3.8ModelMapper 版本吗?您使用的版本是在 records 作为预览功能发布之前创建的。
  • 已更新,但无法正常工作。
  • 那么ModelMapper还不支持record。我建议在他们的 GitHub 存储库上打开一个问题。
  • 与无参构造函数的解析有关,-Define default constructor for record
  • 作为@JacobG。说,以防万一,这是GitHub上的跟踪器-#modelmapper/issues/546

标签: java modelmapper java-14 java-record


【解决方案1】:

记录的字段是最终的,因此必须通过构造函数设置。无论如何,许多框架都会作弊并使用各种技巧来修改最终字段,但这些对记录不起作用。如果要实例化一条记录,则必须在构建时提供所有字段值。

框架可能需要一些时间来了解记录。 “调用无参数构造函数,然后设置字段”的旧模型不适用于记录。一些框架已经能够处理这个问题(例如,“构造函数注入”),而其他框架还没有。但是,我们希望框架能够尽快实现。

正如评论者所说,您应该鼓励您的框架提供者支持他们。不难。

【讨论】:

  • 是的,建筑师先生,但它仍然是 14 中的语言功能,所以在功能交付之前,lombok 听起来很有希望。
【解决方案2】:

record 是 Java 14 中的预览功能,因此我建议您不要在生产环境中使用它。其次,它不模仿 java bean。

record 如果有字段,则没有默认的无参数构造函数。如果您编写了无参数构造函数,则必须将调用委托给所有 args 构造函数,并且由于所有字段都是final,您只能设置一次。所以你有点卡在那里。见JEP 359

向样板宣战不是目标;特别是,使用 JavaBean 命名约定来解决可变类的问题并不是我们的目标。

今天可行的替代方法是使用LombokUserDto 使用 Lombok 的示例:

@NoArgsConstructor
@AllArgsConstructor
@Data
public class UserDto {
    private String firstName;
    private String lastName;
    private String email;
    private String imageUrl;
}

【讨论】:

  • ..另外对于 Lombok vs Record 决定,这里是link to another Q&A
  • 是的,直到它依赖于无参数构造函数来创建一个对象,你可以使用lombok。
  • 感谢您的帮助,但我决定使用其他映射器 - MapStruct。在这个工具中,避免了构造函数的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多