HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Помимо преобразования в DTO, существует и обратная задача - преобразование DTO в Entity. Зачем это делать, если можно наполнять сущность напрямую?</p>
1 <p>Помимо преобразования в DTO, существует и обратная задача - преобразование DTO в Entity. Зачем это делать, если можно наполнять сущность напрямую?</p>
2 <p>Первая причина - это безопасность. Когда у нас есть API для создания или изменения сущности, обычно мы хотим дать возможность менять только часть свойств. Но если мы используем в @RequestBody нашу сущность напрямую, то у клиента API появляется возможность поменять любые свойства сущности:</p>
2 <p>Первая причина - это безопасность. Когда у нас есть API для создания или изменения сущности, обычно мы хотим дать возможность менять только часть свойств. Но если мы используем в @RequestBody нашу сущность напрямую, то у клиента API появляется возможность поменять любые свойства сущности:</p>
3 <p>Мы не советуем использовать userData как сущность и сразу сохранять в базу - такой подход создает потенциальную опасность.</p>
3 <p>Мы не советуем использовать userData как сущность и сразу сохранять в базу - такой подход создает потенциальную опасность.</p>
4 <p>Вторая причина - схема данных. Со временем именование свойств может меняться и в базе данных, и в API - например, при внедрении новой версии. Разделение сущностей и DTO позволяет делать это независимо. DTO представляет внешний интерфейс для API. В свою очередь, сущности описывают внутреннюю модель данных.</p>
4 <p>Вторая причина - схема данных. Со временем именование свойств может меняться и в базе данных, и в API - например, при внедрении новой версии. Разделение сущностей и DTO позволяет делать это независимо. DTO представляет внешний интерфейс для API. В свою очередь, сущности описывают внутреннюю модель данных.</p>
5 <p>Кроме того, существует еще несколько причин, которые мы разберем подробнее в других уроках:</p>
5 <p>Кроме того, существует еще несколько причин, которые мы разберем подробнее в других уроках:</p>
6 <ul><li>Дополнительные преобразования данных перед тем, как они попадут в сущность - например, нормализация электронной почты.</li>
6 <ul><li>Дополнительные преобразования данных перед тем, как они попадут в сущность - например, нормализация электронной почты.</li>
7 <li>Дополнительная валидация, которая может понадобиться в конкретном API. Хорошим примером служит подтверждение пароля. Подтверждение пароля не существует на уровне сущности, это вопрос проверки корректности входных данных.</li>
7 <li>Дополнительная валидация, которая может понадобиться в конкретном API. Хорошим примером служит подтверждение пароля. Подтверждение пароля не существует на уровне сущности, это вопрос проверки корректности входных данных.</li>
8 </ul><p>Преобразование из сущности в DTO и наоборот обычно отличаются набором свойств. Например, в большинстве случаев идентификатор генерируется в базе данных - мы не хотим передавать его в API. При этом при возврате ответа в API мы хотим вернуть идентификатор среди остальных свойств. Поэтому есть смысл создавать разные DTO для этих задач.</p>
8 </ul><p>Преобразование из сущности в DTO и наоборот обычно отличаются набором свойств. Например, в большинстве случаев идентификатор генерируется в базе данных - мы не хотим передавать его в API. При этом при возврате ответа в API мы хотим вернуть идентификатор среди остальных свойств. Поэтому есть смысл создавать разные DTO для этих задач.</p>
9 <p>Разберем пример с созданием и выводом сущности Post:</p>
9 <p>Разберем пример с созданием и выводом сущности Post:</p>
10 <p>Создадим два DTO для каждого действия. Создание потребует три поля - slug, name и body. В вывод добавятся поля id и createdAt:</p>
10 <p>Создадим два DTO для каждого действия. Создание потребует три поля - slug, name и body. В вывод добавятся поля id и createdAt:</p>
11 <p>Реализуем создание и вывод. Вывод потребует преобразования только в DTO, а создание - оба преобразования (из сущности в DTO и наоборот):</p>
11 <p>Реализуем создание и вывод. Вывод потребует преобразования только в DTO, а создание - оба преобразования (из сущности в DTO и наоборот):</p>
12 <p>В методе create() мы поменяли тип входных данных на PostCreateDTO. Уже внутри эти данные копируются в только что созданный объект post. После сохранения в базу данных мы снова выполняем преобразование из Post в PostDTO, чтобы сформировать тело ответа. На этом моменте проявляется разница между тем, что приходит на вход, и тем, что должно быть на выходе. Например, идентификатор появляется только после того, как мы выполняем сохранение в базу данных. Поэтому мы получаем такую цепочку:<em>PostCreateDTO =&gt; Post =&gt; PostDTO</em>.</p>
12 <p>В методе create() мы поменяли тип входных данных на PostCreateDTO. Уже внутри эти данные копируются в только что созданный объект post. После сохранения в базу данных мы снова выполняем преобразование из Post в PostDTO, чтобы сформировать тело ответа. На этом моменте проявляется разница между тем, что приходит на вход, и тем, что должно быть на выходе. Например, идентификатор появляется только после того, как мы выполняем сохранение в базу данных. Поэтому мы получаем такую цепочку:<em>PostCreateDTO =&gt; Post =&gt; PostDTO</em>.</p>