Приходит запрос /entity/1. Нужно вычитать из БД Entity, прибавить к нему несколько свои полей и отдать в JSON-виде. Как лучше организовать классы?
Вариант 1
Создать 2 класса — DBEntity и JSEntity. DBEntity соответствует тому, что мы вытаскиваем из БД, JSEntity соответствует тому, что мы отдаём в JSON-виде. БД- слой вытаскивает DBEntity, контролер копирует все поля в JSEntity, вычисляет недостающие и отдаёт JSON-библиотеке, которая генерирует ответ.
Минусы
Дублирование полей в DBEntity и JSEntity. Можно решить наследованием, но это тупо, т.к. сущности вообще говоря разные и какие то поля могут не пригодиться в ответе.
Boilerplate код по копированию большинства полей из DBEntity в JSEntity. Можно автоматизировать, но мне почему то этот вариант не нравится (не знаю, почему, вижу какие то смутные проблемы по всяким конфигураторам преобразований типов и трудноотлаживаемым глюкам).
Вариант 2
Создать 1 класс Entity, включающий в себя все поля. БД слой заполняет свои поля, контролер заполняет оставшиеся, JSON-библиотека настраивается, чтобы использовать нужные поля (аннотациями например).
Минусы
На класс ложится несколько ответственностей.
Скорее всего будет куча аннотаций навешано, что сделает его трудночитаемым.
Обдумывал варианты без создания класса, например используя Map<String, Object> либо для БД либо для JSON, но преимущества перед первым вариантом не увидел, а недостатки в виде потери статического контроля есть.
В принципе склоняюсь к варианту 1, т.к. минусы там больше эстетические. Хотелось бы в частности услышать мнение о целесообразности использования автоматического копирования свойств из одного объекта в другой. Пока думаю, что это имеет смысл, если указывать вручную список всех полей (чтобы не терять контроль над тем, какие поля копируются) и если типы совпадают или преобразование тривиально (int -> Integer). Любое нетривиальное преобразование — делать руками, пусть даже setData(getData().toString()), волшебство под капотом ненавижу.