DTO – Data Transfer Object

  • Рубрика записи:Spring back-end

Далеко не всегда дело обходится одними только объектами слоя entity. Порой нужно создать классы, которые напоминают классы сущностей, но они будут упрощены или модифицированы. Это делается для нужд транспортировки данных. Отсюда и название – DTO, Data Transfer Object.

Предлагаю приступить к обсуждению, зачем используются DTO, какие принципы есть при создании DTO и как их вообще создавать.

Что такое DTO и зачем нужны

DTO представляют собой объекты, которые используются для передачи данных между различными частями приложения. Они служат в качестве контейнеров для данных и обычно содержат только поля данных и методы доступа к этим данным.

Использование DTO в структуре Spring-проекта помогает разделить бизнес-логику приложения от его представления и обеспечивает более гибкую структуру. Они также уменьшают объём данных, передаваемых между клиентом и сервером, а это, на минуточку, оптимизация нагрузки на сеть.

Ещё одна немаловажная причина использовать DTO – возможность рекурсивного доступа объектов друг к другу. Например, сущность Author имеет в списке список объектов Book. Сущность Book, в свою очередь, имеет в себе поле Author. Таким образом, при передаче объекта Book или Author клиенту как JSON-объект, мы столкнёмся со StackOverflowError. Это ошибка из иерархии ошибок и исключений в Java, которая возникает при переполнении стека. А переполнился он, потому что две сущности бесконечно переводили стрелки друг на друга, не сумев остановиться на ком-то одном. Вот DTO-шки и приходят на помощь – обычно с нейтрализацией в одной из двух сущностей ссылки на другую сущность.

Как создать DTO

Для создания DTO в Java обычно используются простые классы с private полями данных и public методами доступа к этим полям. Например, та же книжка Book, но уже без ссылки на автора Author:

Заметьте, что я называю класс не BookDTO, а BookDto. Всё из-за соглашения о кодировании на языке Java, конвенции о написании кода. Там говорится, что аббревиатуры лучше писать не капсом, а как обычное слово. Так названия классов лучше читаются, когда слов несколько – сразу видны их границы. Например, HttpRequest явно лучше, чем HTTPRequest.

Виды

DTO могут быть различных типов в зависимости от контекста приложения и специфики данных, которые необходимо передавать. В основном DTO бывают такого рода:

  1. Request. Используется для передачи данных от клиента к серверу.
  2. Response. Используется для передачи данных от сервера к клиенту в ответ на запросы клиента.
  3. Entity. Используется для передачи данных сущностей между различными слоями приложения.

В нашем с вами случае это будут Request и Response DTO, так как наше Spring-приложение может принимать и отдавать данные.

Пример с User и Post

Итак, вернёмся к примеру созданных ранее сущностей User и Post, которые были написаны по образу и подобию таблиц users и posts в БД.

Сущность User выглядит так:

Вот так выглядит сущность Post:

И да, они ссылаются друг на друга. Давайте уберём одну из связей, чтобы избежать рекурсии. Условимся, что клиенту, получающему DTO от сервера, будет важнее знать пользователя, написавшего запись в сущности Post, чем получать список всех записей пользователя в сущности User. Ведь список всех записей по пользователю можно и так произвести при помощи соответствующего запроса.

Итак, убираем связь со стороны User. Также я не буду прописывать геттеры и сеттеры, а также класс-строитель Builder своими руками. Я для этого буду использовать библиотеку Lombok, которая позволит мне сделать это в несколько аннотаций: @Getter, @Setter и @Builder.

Вот как будет выглядеть DTO для сущности пользователя:

Да, такой маленький и миленький класс. Удивительные чудеса творят современные инструменты разработки. А вот DTO для сущности записи:

Учтите, что ссылки на другие сущности в классе DTO должны быть заменены также на DTO. То есть в PostDto используется поле UserDto, а не User.

Неплохо поработали!

DTO мы создали. Что делать дальше? Как их применить? А для этого нам потребуются специальные конвертеры. Они будут конвертировать entity в Data Transfer Object и обратно. Такие конвертеры называются mapper-ы. И о них – в следующей статье.

Добавить комментарий