Как я могу использовать Java записей в качестве DTO с ModelMapper? - PullRequest
1 голос
/ 18 июня 2020

Я занимаюсь рефакторингом своего кода. Я хочу использовать java записей вместо java класса в моем DTO. Чтобы преобразовать DTO в Entity, я использую ModelMapper (версия 2.3.5). Когда я пытаюсь получить информацию о пользователе (метод вызова co convert Entity to 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 ]

8 голосов
/ 20 июня 2020

Поля записи являются окончательными, поэтому они должны быть установлены через конструктор. Многие фреймворки в любом случае обманывают и используют различные уловки для изменения полей final, но они не будут работать с записями. Если вы хотите создать экземпляр записи, вы должны предоставить все значения полей во время построения.

Платформам может потребоваться некоторое время, чтобы узнать о записях. Старая модель «вызвать конструктор без аргументов, а затем установить поля» не будет работать для записей. Некоторые фреймворки уже могут справиться с этим (например, «внедрение конструктора»), в то время как других еще нет. Но мы ожидаем, что фреймворки появятся достаточно скоро.

Как сказали комментаторы, вы должны поощрять своего поставщика фреймворка поддерживать их. Это несложно.

2 голосов
/ 18 июня 2020

record - это функция предварительного просмотра в Java 14, поэтому я бы не рекомендовал вам использовать ее в продакшене. Во-вторых, он не имитирует c java bean.

record не имеет конструктора по умолчанию no arg неявно, если есть поля. Если вы написали конструктор без аргументов, вам придется делегировать вызов всем конструкторам аргументов, а поскольку все поля имеют размер final, вы можете установить их только один раз. Так что вы как бы застряли там. См. JEP 359 :

Объявление «войны шаблону» не является целью; в частности, не ставится цель решить проблемы изменяемых классов с использованием соглашений об именах JavaBean.

Альтернативой, которая работает сегодня, было бы использование Lombok. Пример UserDto с использованием Lombok:

@NoArgsConstructor
@AllArgsConstructor
@Data
public class UserDto {
    private String firstName;
    private String lastName;
    private String email;
    private String imageUrl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...