0

在我的实体 ( myGroup : Group) 上,我有一个集合属性 ( members : HashMap<Long, GroupMember>),我希望允许用户向地图添加多个新的(未持久化GroupMember的) myGroup.members

  • 我为集合属性使用哈希图的原因是为了确保集合的使用是高性能的(即GroupMember在业务逻辑执行期间必须能够通过其 ID 快速多次获取 a)。

  • 我不想立即保留它们的原因是支持添加的还原。用户必须能够操作myGroup.members映射,添加和删除成员直到满意,然后再持久化(在 Hibernate 会话中保存实体并刷新)。

问题GroupMember必须为 new 分配一个 ID 为零,以便 Hibernate 检测到它们未保存。(*) 因为成员位于映射中,由 ID 键入,这意味着只能添加一个新成员保存或还原。添加第二个 ID 为 0 的新成员会简单地覆盖(引用)第一个成员。

我的问题是如何最好地调整我的代码解决方案以支持将多个未保存的实体添加到集合(myGroup.members)中,同时保持使用哈希映射或其他映射/字典的性能优势?

注意:我已经尝试过一种 hack,其中 ID 来自GroupMember实例中数据的唯一组合,然后,在保存之前,ID 设置为零,以便 Hibernate 检测到它需要被持久化,但它是不优雅,我还没有找到让它可靠工作的方法。

* 我不完全理解 Hibernate 在这方面的行为。

Group以下实体的缩写代码:

@Entity
@Table (name="GROUP")
public class Group
{
    private Map<Long,GroupMember> members = new HashMap<Long,GroupMember>();

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "ownerGroup", cascade = { CascadeType.ALL })
    @MapKey(name="id")
    public Map<Long,GroupMember> getMembers() { return this.members; }

    public void setMembers(Map<Long,GroupMember> members) { this.members = members; }

    // ...other properties and methods...
}
4

1 回答 1

1

我对你要达到的目标有点困惑。未持久化的成员没有任何 ID。当您使用 ID 作为键时,您期望这些成员的“查找”行为是什么?对我来说,您可以通过 ID 查找新成员似乎不合理,因为他们还没有任何身份。

如果不需要查找新成员,我会建议你:

  1. 存储“新成员”的单独属性
  2. 在您的实体中有方法 commit() 和 revert()
  3. 用户将在完成更新后调用 commit(),然后将新实体移动到实际的“映射”映射/列表以实现实际持久性

如果需要查找新成员,并且从您的段落来看,您似乎能够自己生成经过验证的唯一密钥,您是否会考虑不让休眠来为您生成 ID?您可以在 Hibernate 中选择该 ID 是由 Hibernate 生成(作为代理键)还是由您提供(一种自然键)。我相信自行提供的 ID 更适合您的情况,因为您似乎没有将 ID 视为代理键。


编辑:关于OP关于无法单独存储它的原因的评论,可以通过这种方法轻松解决(我认为它也更有意义):

(普塞多代码)

class Group {
  private List<Member> members;  // mapped in hibernate
  private List<Member> unsavedMembers;  // unmapped

  public Map<Long, Member> getProposedMemberMap() {
    // returned the combined "view" members and unsavedMembers
  }

  @PreUpdate  // you may consider running it it pre-update too
  public void commit() {
    members.addAll(unsavedMembers);
    unsavedMembers.clear();
  }

  public void revert() {
    unsavedMembers.clear();
  }
}

通过这样做,您可以查看“建议的成员”以进行迭代,同时分别存储实际和未保存的成员。

于 2012-06-27T03:27:44.163 回答