Spring Boot
Теория: Преобразование DTO в сущность
Помимо преобразования в DTO, существует и обратная задача — преобразование DTO в Entity. Зачем это делать, если можно наполнять сущность напрямую?
Первая причина — это безопасность. Когда у нас есть API для создания или изменения сущности, обычно мы хотим дать возможность менять только часть свойств. Но если мы используем в @RequestBody нашу сущность напрямую, то у клиента API появляется возможность поменять любые свойства сущности:
Мы не советуем использовать userData как сущность и сразу сохранять в базу — такой подход создает потенциальную опасность.
Вторая причина — схема данных. Со временем именование свойств может меняться и в базе данных, и в API — например, при внедрении новой версии. Разделение сущностей и DTO позволяет делать это независимо. DTO представляет внешний интерфейс для API. В свою очередь, сущности описывают внутреннюю модель данных.
Кроме того, существует еще несколько причин, которые мы разберем подробнее в других уроках:
- Дополнительные преобразования данных перед тем, как они попадут в сущность — например, нормализация электронной почты.
- Дополнительная валидация, которая может понадобиться в конкретном API. Хорошим примером служит подтверждение пароля. Подтверждение пароля не существует на уровне сущности, это вопрос проверки корректности входных данных.
Преобразование из сущности в DTO и наоборот обычно отличаются набором свойств. Например, в большинстве случаев идентификатор генерируется в базе данных — мы не хотим передавать его в API. При этом при возврате ответа в API мы хотим вернуть идентификатор среди остальных свойств. Поэтому есть смысл создавать разные DTO для этих задач.
Разберем пример с созданием и выводом сущности Post:
Создадим два DTO для каждого действия. Создание потребует три поля — slug, name и body. В вывод добавятся поля id и createdAt:
Реализуем создание и вывод. Вывод потребует преобразования только в DTO, а создание — оба преобразования (из сущности в DTO и наоборот):
В методе create() мы поменяли тип входных данных на PostCreateDTO. Уже внутри эти данные копируются в только что созданный объект post. После сохранения в базу данных мы снова выполняем преобразование из Post в PostDTO, чтобы сформировать тело ответа. На этом моменте проявляется разница между тем, что приходит на вход, и тем, что должно быть на выходе. Например, идентификатор появляется только после того, как мы выполняем сохранение в базу данных. Поэтому мы получаем такую цепочку: PostCreateDTO => Post => PostDTO.



