配置hibernate以检索集合而不持久化它

时间:2011-11-29 22:59:11

标签: java hibernate jpa

数据库:

我有一个名为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_RolesUser持续存在时,Account.users的更新。同样,我希望在从数据库中提取帐户时使用Users_Accounts_Roles中的数据填充Accounts.users,但我不希望更改Users_Accounts_Roles来影响{{1}的更新当Account被持久化时。 Users_Accounts_Roles表格应该更改的唯一方法是User是否与更新的accountRoles字段保持一致。

按原样,User.accountRoles映射正在按照我的喜好(从Users_Accounts_Roles检索并持久保存),但我找不到User.accounts和{{1}的方法分别在Account.usersUser抓取时检索,但在AccountUser持久化时不会保留,而不在DAO层中使用某些丑陋的逻辑。 (它们目前被标记为瞬态,因为我没有尝试过任何其他工作)。 Hibernate / JPA是否支持我正在尝试做的事情?

- - - - - - - - 编辑

我怀疑我的解决方案可能涉及在Account@OneToMany(mappedBy="...")上使用User.accounts,如同this tutorial中所做的那样。但是,我无法弄清楚如何对Account.usersAccountRole字段中的字段进行注释,以便对后者的更改仍然保留。

1 个答案:

答案 0 :(得分:0)

您可以尝试使用user.accounts@ManyToMany映射为@JoinTable(name ="Users_Accounts_Roles", joinColumns=...)。默认情况下,@*ToMany不会级联任何内容,因此您不会冒错误添加/删除条目。但是,修改Account本身将被保留,但这只是因为它们是托管实体。无论如何,那些Account对象将与通过user.accountRoles集合链接的对象相同,所以我想这应该不是问题。

注意这种解决方案的性能,因为它可能导致执行大量查询(例如,为每个用户提取一个额外的查询以获取他的帐户)。

或者你可以简单地实现一个(只读)Collection<Account>包装器,它将所有调用委托给user.accountRoles集合(只需在getAccount()个对象上调用AccountRole它返回)。这样您就可以控制每个操作,并确保只获取一次关系。