Разработка DTO, которые имеют отношения с внешним ключом - PullRequest
8 голосов
/ 07 января 2012

Я использую Java + Spring Framework для веб-приложения.Я не использую какой-либо инструмент ORM.Вместо этого я пытаюсь смоделировать отношения БД как объекты Java, используя простой шаблон DAO / DTO.Всякий раз, когда DTO точно соответствует одной таблице в базе данных, это очень просто.Но если есть таблицы, которые ссылаются на другие таблицы с использованием внешних ключей, я не уверен, что лучше всего подходит для этого.Посмотрел в Stackoverflow похожие ответы, но не смог найти ни одного, соответствующего моим потребностям.Я хочу привести очень конкретный пример. Предположим, есть две сущности: Пользователь и Группа.У меня есть пользовательский DTO и Group DTO, каждый из которых имеет UserDao (JdbcUserDao) и GroupDao (JdbcGroupDao) соответственно.

Теперь у меня есть отношение в БД, которое соединяет пользователя и группу.Один пользователь может принадлежать нескольким группам.Имя таблицы - User_Group_Association со следующим определением БД:

user_id |group_id

Здесь user_id - это внешний ключ, относящийся к пользовательской таблице.Аналогично, group_id ссылается на таблицу групп.Когда я моделирую этот DTO в Java, я должен сделать что-то вроде этого:

public class UserGroupAssoc {
    private int userId;
    private int groupId;

    //Setters and getters follow
}

ИЛИ это должно быть так:

public class UserGroupAssoc {
    private User user;
    private Group group;

    //Setters and getters follow
}

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

1014 * Имя -> Имена групп

Кешав -> Администратор, Конечный пользователь, ReportAdmin
Киран -> ReportAdmin
Пранав -> Конечный пользователь

ВПри первом подходе к проектированию DTO мне нужно будет снова получить информацию о пользователях (имена) и сведения о группе (имена) из БД.Во втором подходе мне нужно будет извлекать объекты User и Group при создании самого объекта UserGroupAssoc.

В третьем подходе я могу создать DTO UserGroupAssoc следующим образом:

public class UserGroupAssoc {
    private String userName;
    private String groupName;
    private int userId;
    private int groupId;

    //Setters and getters follow
}

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

Какой стандартный подход используется для реализации этого сценария?Хорошо ли объединение таблиц в дизайне DTO?Некоторые считают, что один DTO должен соответствовать только ОДНОЙ таблице, а связанные объекты должны агрегироваться на уровне приложения.Это накладные расходы на выполнение нескольких выборок объектов из БД, верно?Слишком запутался по поводу правильного подхода, извините за такое длинное объяснение!

1 Ответ

6 голосов
/ 08 января 2012

Отказ от ответственности: я не специалист по ORM ...

... но в классических отношениях многих ко многим вам не нужна третья модель данных (UserGroupAssoc).Класс User будет содержать коллекцию Group s:

public class User {
   // ... user fields ...
   List<Group> groups;
   // ... getters/setters ...
}

Если вам необходимо также обратное отношение (группа содержит пользователей), класс Group будет выглядеть следующим образом:

public class Group {
   // ... group fields ...
   List<User> users;
   // ... getters/setters ...
}

И снова, классический способ сделать это - использовать в коллекции «доменные объекты» (ваши DTO) (User и Group вместо userId и groupId).

Третий объект домена обычно требуется только в том случае, если таблица ассоциации (User_Group_Association) содержит что-то еще, кроме user_id и group_id (может быть, некоторый код авторизации, который позволил добавить пользователя в группу, что угодно):

user_id | group_id | auth_code

В этом случае класс UserGroupAssoc может иметь такую ​​структуру:

public class UserGroupAssoc {
    private User user;
    private Group group;
    private String authorizationCode;

    // ... setters/getters ...
}

И отношение «многие ко многим» между User и Group преобразуетсядо двух отношений «один к одному» с этим новым объектом домена.Обычно доменные объекты предпочтительнее использовать (User и Group вместо userId и groupId).

Какой стандартный подход используется для реализации этого сценария?

Ну, если бы вы использовали ORM-фреймворк, это был бы стандартный способ, которым фреймворк делал это.Но , поскольку у вас есть собственное решение ORM, трудно сказать.

Хорошо ли объединение таблиц в дизайне DTO?

Почему проект DTO на уровне приложений должен зависеть от объединения таблиц в базе данных?Это случай несоответствия объектно-реляционного импеданса , а также, возможно, закона утечки абстракции , поскольку вы не можете полностью абстрагировать реляционную область в объектную область, сохраняя 1: 1переписка.

Некоторые считают, что один DTO должен соответствовать только ОДНОЙ таблице, а связанные объекты должны агрегироваться на уровне приложения.Это накладные расходы на выполнение нескольких выборок объектов из БД, верно?

ORM имеет некоторые ограничения (см. Снова несоответствие объектно-реляционного импеданса для некоторых проблем, с которыми вы можете столкнуться), и сложно моделировать ваши доменные объекты, чтобы приспособиться к ограничениям реляционной базы данных, или наоборот-versa.Отчеты являются хорошим примером в этом направлении.

Отчет обычно объединяет данные из нескольких таблиц.Это, конечно, не проблема для некоторых соединений SQL, но как вы собираетесь сопоставить результат с DTO?Как вы сами сказали ...

Всякий раз, когда DTO точно соответствует одной таблице в базе данных, это очень просто

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

В зависимости от ваших потребностей в приложении, вы можете получить странные классы или неуклюжиеSQLs.Вы можете выполнить больше запросов, чем необходимо для получения надлежащих объектных моделей и связей между ними;или у вас может быть больше подобных DTO только для того, чтобы ограничить число поездок в базу данных и повысить производительность.

Итак, я пытаюсь сказать (опять же, отказ от ответственности, что я не специалист ORM)что не все приложения являются хорошим кандидатом на ORM;но если вы подумаете о том, чтобы пойти дальше, возможно, посмотрите, как Hibernate / JPA решает проблемы, или даже используйте их вместо этого.

...