2012-08-14 106 views
1

我已经看了很多帖子对这个话题,但一直没能解决这个问题=(Hibernate的级联保存父/子与测序FK

我试图拯救父母和孩子有一个一我相信我遵循文档和其他帖子的其他建议,但是,我遇到的问题是,当Hibernate尝试保存子记录时,它将FK插入“0”给父项的,而不是真正的ID。

父的hbm.xml映射

<hibernate-mapping> 
<class name="ParentClass" table="PARENTTABLE"> 
    <id name="parentid" type="java.lang.Long"> 
     <column name="PARENTID" precision="15" scale="0" /> 
     <generator class="sequence"> 
      <param name="sequence">S_PARENTTABLE</param> 
     </generator> 
    </id> 
... 
    <set name="children" table="CHILDTABLE" inverse="true" lazy="true" fetch="select" cascade="all"> 
     <key> 
      <column name="PARENTID" precision="15" scale="0" not-null="true" /> 
     </key> 
     <one-to-many class="ParentClass" /> 
    </set> 
... 
</class> 
</hibernate-mapping> 

孩子的hbm.xml映射

<hibernate-mapping> 
<class name="ChildClass" table="CHILDTABLE"> 
    <composite-id name="id" class="ChildClassId"> 
     .... 
     <key-property name="parentid" type="long"> 
      <column name="PARENTID" precision="15" scale="0" /> 
     </key-property> 
    </composite-id> 
    <many-to-one name="parent" class="ParentClass" update="false" insert="false" fetch="select"> 
     <column name="PARENTID" precision="15" scale="0" not-null="true" /> 
    </many-to-one> 
.... 
</class> 
</hibernate-mapping> 

Java代码保存对象

private myMethod(ParentClass p, HashSet<ChildClass> children){ 
    for(ChildClass child : children){ 
     child.setParent(p); 
    } 
    p.setChildren(children); //The parameter type is Set<ChildClass> 
    sess.save(p); 
    ... 
} 

因此,这将保存正确的ID父对象(下一序列值,说273)但是当它去,并试图保存子对象,而不是使用273,它只是使用0.

我不能figur e如何让Hibernate用正确的ParentId(FK)保存子对象。

任何帮助你可以提供或任何想法将非常感激!提前致谢!

** UPDATE ** 我终于弄清楚为什么子表中的FK没有插入正确的值。这是由于映射定义。我在我的数据库上运行了一个反向工程师,并且选中了一个表示'生成基本类型化合成ID'的框。这导致Hibernate将复合键列映射为基本类型,而不是对实体的引用。当我做插入时,这有点让人困惑。

正确的子表映射应该看起来更像是这样的:

更新孩子的hbm.xml映射

<hibernate-mapping> 
<class name="ChildClass" table="CHILDTABLE"> 
    <composite-id name="id" class="ChildClassId"> 
     .... 
     <key-many-to-one name="parentid" class="ParentClass" > 
      <column name="PARENTID" precision="15" scale="0" /> 
     </key-many-to-one> 
    </composite-id> 
</class> 
</hibernate-mapping> 

通知的标签,而不是从之前的标签。此外,标签外的标签已经消失(或者更确切地说,将标签作为标签移动到标识中)。

回答

0

我认为在你的情况下,你应该在父类的一对多映射定义中将inverse属性设置为false。这意味着您的父实体将负责更新子表中的FK。在这种情况下,休眠将在保存父实体后执行额外的更新语句以更新子表中的FK。

<set name="children" inverse="false" lazy="true" fetch="select" cascade="all"> 
     <key> 
      <column name="PARENTID" precision="15" scale="0" not-null="true" /> 
     </key> 
     <one-to-many class="ParentClass" /> 
</set> 
+0

嗨迪马斯,感谢您的回复=)。我实际上已经尝试过了,它似乎没有区别..? = |所以我做了一个sess.save然后sess.flush。在我的日志中,我看到当我进行保存时,Hibernate首先获取序列值(nextval)。然后,它会为父和子记录进行选择。在这个阶段,它已经在选择孩子时使用'0'作为参数。然后最后,在刷新,它插入到正确的ID,然后它插入到子表,但与'0',我得到我的错误=( – ZeroK178 2012-08-15 15:48:17

+0

好吧。尝试从父实体的集合定义中移除table =“CHILDTABLE”,并从子类的多对一定义中移除class =“ParentClass”。 – dimas 2012-08-16 11:08:47

+0

嗨迪马斯,感谢您的回复和建议,但不幸的是,这也没有奏效。但我设法弄清楚它是什么! =)我用我所做的更新了我的问题。再次感谢! – ZeroK178 2012-08-20 19:41:51