我正在尝试将两个集合映射到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
。但是,在这种情况下,两者都不接缝以支持这些属性。
如何判断集合或列表不进行任何更新或插入?
答案 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。所以现在的行为就像只读一样。