在hibernate映射中对set / list进行插入更新控制

时间:2014-09-15 17:31:23

标签: xml hibernate insert-update

我正在尝试将两个集合映射到hibernate 3映射中的同一个id列。 objectSet是“历史性的”,我被要求保留在那里。 idSet是一种新的解决方案,如果集合变大(一百万个),它将具有更好的性能。

<set cascade="none" name="objectSet" table="TBL_A_HAS_B" lazy="true" >
  <key column="A_ID" />
  <many-to-many class="test.B" column="B_ID" unique="true" />
</set>
<set name="idSet" table="TBL_A_HAS_B" lazy="true" >
  <key column="A_ID" />
  <element column="B_ID" type="string" not-null="true"/>
</set>

我希望idSet成为领先者。因此,插入和更新只能通过idSet完成。 objectSet应该只是数据的第二个详细视图。

要实现我尝试在集合或insert="true"上设置update="true"many-to-one。但是,在这种情况下,两者都不接缝以支持这些属性。

如何判断集合或列表不进行任何更新或插入?

2 个答案:

答案 0 :(得分:0)

我希望您应该通过更改级联选项来控制行为。将一个设置为&#34;无&#34;另一个是&#34;保存更新&#34;或任何合适的东西。我没试过这个,但听起来不错。请注意脏检查机制 - 请参阅here了解更多详情。

答案 1 :(得分:0)

我找到了一个可能比我最初想要的更有意义的解决方案。

我将mutable="false"添加到映射中,因此不再允许对objectSet进行更改。 (在这里查看更多细节Java Immutable Collections。)我仍然可以更改idSet,但这会导致两个列表不同步。

<set cascade="none" name="objectSet" table="TBL_A_HAS_B"
  lazy="true" mutable="false" >
  <key column="A_ID" />
  <many-to-many class="test.B" column="B_ID" unique="true" />
</set>

可以通过调用hibernateSession.refresh(instanceOfB);

再次同步这些集
public class B {

  private Set<C> objectSet = new HashSet<C>();
  private Set<String> idSet = new HashSet<String>();

  public Set<String> getIdSet() {
    return idSet;
  }

  public void setIdSet(Set<String> idSet) {
    this.idSet = idSet;
  }

  @Deprecated
  public Set<C> getObjectSet() {
    return Collections.unmodifiableSet(objectSet);
  }

  protected void setObjectSet(Set<C> objectSet)
  {
    this.objectSet= objectSet;
  }

  @Deprecated
  public final void replaceObjectSet(Set<C> objectSet)
  {
    if (objectSet != null) {
      if (idSet== null) {
        idSet= new HashSet<String>(objectSet.size());
      } else {
        idSet.clear();
      }
      for (C object : objectSet) {
        try {
          idSet.add(object.getId());
        }
        catch (Exception e) {
          continue;
        }
      }
    }
  }

}
  • getObjectSet()返回一个集合,其元素可以更改,但无法添加或删除。尝试添加,删除或清除该集合将引发JAVA异常。如果没有那个换行,一旦flush()发生或被强制,你只会得到一个hibernate异常。我将其设置为已弃用(带有解释注释),因此会收到警告并阻止对它的任何使用,因为当集合变大并且可能不同步时可能会出现性能问题。

  • setObjectSet(..)受到保护,因此无法公开访问,同时仍允许hibernate在请求时调用它来设置数据。

  • replaceObjectSet()setObjectSet(..)的“新公开版本”,因此可以轻松调整旧代码,但必须使用新系统。它也被弃用了idSet的链接。

如果这是一个很好的解决方案,或者如果你有一个更好的解决方案,任何评论都是受欢迎的。

编辑1:

这似乎不是完整的答案。 mutable="false"(至少本身)确实不等于只读。当对idSet进行更改并持久化时,Hibernate将首先基于idSet添加一个新的id,然后再次删除它们,因为objectSet不包含它们,因为immutable永远不会改变。

解决方案是添加inverse="true"

通过告诉Hibernate关联的另一端将处理更新,它将忽略它的映射。由于关联的另一端不存在,其他任何东西都不会写入objectSet的id。所以现在的行为就像只读一样。