Настройка режима гибернации для получения коллекции без ее сохранения - PullRequest
4 голосов
/ 30 ноября 2011

База данных:

У меня есть таблица трехстороннего соединения под названием Users_Accounts_Roles.

+--------------+------------+------+-----+-------------------+----------------+
| Field        | Type       | Null | Key | Default           | Extra          |
+--------------+------------+------+-----+-------------------+----------------+
| id           | bigint(20) | NO   | PRI | NULL              | auto_increment |
| user_id      | bigint(20) | NO   | MUL | NULL              |                |
| account_id   | bigint(20) | NO   |     | 0                 |                |
| role_id      | bigint(20) | NO   |     | NULL              |                |
+--------------+------------+------+-----+-------------------+----------------+

Пользователи могут принадлежать к нескольким учетным записям и могут иметь несколько ролей для каждой из этих учетных записей.

У меня также есть User стол

+----------------+--------------+------+-----+---------------------+-----------------------------+
| Field          | Type         | Null | Key | Default             | Extra                       |
+----------------+--------------+------+-----+---------------------+-----------------------------+
| id             | bigint(20)   | NO   | PRI | NULL                | auto_increment              |
| email          | varchar(255) | NO   | UNI | NULL                |                             |
| firstName      | varchar(255) | NO   |     | NULL                |                             |
| lastName       | varchar(255) | NO   |     | NULL                |                             |
+----------------+--------------+------+-----+---------------------+-----------------------------+

Account стол

+--------------+-------------+------+-----+---------------------+-----------------------------+
| Field        | Type        | Null | Key | Default             | Extra                       |
+--------------+-------------+------+-----+---------------------+-----------------------------+
| id           | bigint(20)  | NO   | PRI | NULL                | auto_increment              |
| name         | varchar(50) | NO   |     | NULL                |                             |
+--------------+-------------+------+-----+---------------------+-----------------------------+

И Role стол

+--------------+--------------+------+-----+---------------------+----------------+
| Field        | Type         | Null | Key | Default             | Extra          |
+--------------+--------------+------+-----+---------------------+----------------+
| id           | bigint(20)   | NO   | PRI | NULL                | auto_increment |
| name         | varchar(255) | NO   |     | NULL                |                |
| description  | text         | NO   |     | NULL                |                |
+--------------+--------------+------+-----+---------------------+----------------+

Объекты (редко):

@Embeddable
AccountRole {
  ...

  @Parent
  User getUser() {
    return user;
  }

  @ManyToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "account_id")
  Account getAccount() {
    return account;
  }

  @ManyToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "role_id")
  Role getRole() {
    return role;
  }

  ...
}

@Entity
User {
  ...

  @Transient
  Set<Account> getAccounts() {
    return accounts;
  }

  @ElementCollection(fetch = FetchType.EAGER)
  @JoinTable(name = "Users_Accounts_Roles", joinColumns = @JoinColumn(name = "user_id"))
  Set<AccountRole> getAccountRoles() {
    return accountRoles;
  }

  ...
}

@Entity
Account {
  ...

  @Transient
  Set<User> users;

  ...
}

Я хочу, чтобы User.accounts заполнялся данными в Users_Accounts_Roles, когда User выбирается из базы данных, но я не хочу изменений вUser.accounts, чтобы повлиять на обновления до Users_Accounts_Roles, когда User сохраняется.Точно так же я хочу, чтобы Account.users заполнялся данными в Users_Accounts_Roles, когда учетная запись выбирается из базы данных, но я не хочу, чтобы изменения в Accounts.users влияли на обновления в Users_Accounts_Roles, когда Accountсохранялось.Единственный способ изменить таблицу Users_Accounts_Roles - это сохранить User с обновленным полем accountRoles.

Как и раньше, отображение User.accountRoles работает мне по вкусу (как извлечение из, так и изсохраняется до Users_Accounts_Roles), но я не могу найти способ извлечения User.accounts и Account.users при User и Account выборке соответственно, но не сохраняется при User или Accountсохраняется без использования некрасивой логики на уровне DAO.(В настоящее время они помечены как временные, так как ничего другого, что я пробовал, не сработало).Поддерживает ли Hibernate / JPA то, что я пытаюсь сделать?

----- EDIT -----

Я подозреваю, что мое решение может включать использование @OneToMany(mappedBy="...") на User.accountsи Account.users, как сделано в этого урока .Однако я не могу понять, как аннотировать поля в AccountRole и поле User.accountRoles, чтобы сделать так, чтобы изменения в последнем все еще сохранялись.

1 Ответ

0 голосов
/ 13 февраля 2012

Вы можете попробовать сопоставить user.accounts с @ManyToMany, используя @JoinTable(name ="Users_Accounts_Roles", joinColumns=...). По умолчанию @*ToMany ничего не каскадирует, поэтому вы не рискуете добавлять / удалять записи по ошибке. Однако изменение самих Account будет продолжено, но это только из-за того, что они являются управляемыми объектами. В любом случае, эти Account объекты будут такими же, как те, которые связаны с коллекциями user.accountRoles, поэтому я думаю, что это не должно быть проблемой.

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

В качестве альтернативы вы могли бы просто реализовать (101) * оболочку (только для чтения), которая делегировала бы все ее вызовы в коллекцию user.accountRoles (просто вызывая getAccount() для объектов AccountRole, которые она возвращает). Таким образом, вы можете контролировать каждую операцию и убедиться, что отношение выбирается только один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...