如何在Hibernate会话中管理未保存实体的映射?

时间:2012-06-27 02:50:26

标签: hibernate map revert hibernate-session

在我的实体(myGroup : Group)上我有一个集合属性(members : HashMap<Long, GroupMember>),我希望允许用户向{{1}添加多个新的(未显示的)GroupMember地图。

  • 我为集合属性使用散列图的原因是为了确保集合的使用是高效的(即必须能够在执行期间快速多次获取myGroup.members ID业务逻辑)。

  • 我不想立刻坚持下去的原因是为了支持这些补充的回归。用户必须能够操作GroupMember地图,添加和删除成员,直到满意为止,然后保持(在Hibernate会话中保存实体并刷新)。

问题是必须为新的myGroup.members分配ID为零,以便Hibernate检测到它们未被保存。(*)因为成员位于地图中,所以键入通过ID,这意味着在保存或还原之前只能添加一个新成员。添加ID为零的第二个新成员只会覆盖(引用)第一个。

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

注意:我已经尝试过一个hack,其中ID是从myGroup.members实例中的唯一数据组合派生的,然后,在保存之前,ID被设置为零,以便Hibernate检测到它需要坚持,但它不够优雅,我没有办法让它可靠地工作。

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

以下GroupMember实体的缩写代码:

Group

1 个答案:

答案 0 :(得分:1)

我对你要实现的目标感到有些困惑。不持久的成员没有任何ID。当您使用ID作为密钥时,您对这些成员的“查找”行为有何期待?我可以通过ID查找新成员似乎不合理,因为他们还没有任何身份。

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

  1. 存储“新成员”的单独属性
  2. 在您的实体中使用方法commit()和revert()
  3. 用户将在完成更新时调用commit(),然后新实体将被移动到实际的“映射”地图/列表以实现持久性
  4. 如果需要查找新成员,并且从您的文章开始,您似乎有能力自己生成经过验证的唯一密钥,您是否会考虑不使用hibernate来为您生成ID?您可以在Hibernate中选择是否由Hibernate生成ID(作为代理键)并由您提供(一种自然键)。我相信自己提供的ID更适合您的情况,因为您似乎没有将ID视为代理密钥。


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

    (pusedo代码)

    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();
      }
    }
    

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