我有两个类,称为Monkey和Banana,具有一对多的双向关系。
Monkey monkey = new Monkey();
Banana banana = new Banana();
monkey.Bananas.Add(banana);
banana.Monkey = monkey;
hibernateService.Save(banana);
当我运行那段代码时,我希望持久化猴子和香蕉。然而,它只是在我明确保存猴子时才持久,反之亦然。最初,这是有道理的,因为只有我的Monkey.hbm.xml具有cascade="all"
的映射。
<set name="Bananas" inverse="true" cascade="all">
<key column="Id"/>
<one-to-many class="Banana"/>
</set>
我想我只需要将以下内容添加到我的Banana.hbm.xml文件中:
<many-to-one name="Monkey" column="Id" cascade="all" />
不幸的是,当我尝试运行代码段时,这会导致Parameter index is out of range
错误。我调查了这个错误并发现this post,但我仍然没有看到我做错了什么。据我所知,我在每一侧都有一次映射关系。有关完整披露,以下是两个映射文件:
Monkey.hbm.xml
<class name="Monkey" table="monkies" lazy="true">
<id name="Id">
<generator class="increment" />
</id>
<property name="Name" />
<set name="Bananas" inverse="true" cascade="all">
<key column="Id"/>
<one-to-many class="Banana"/>
</set>
</class>
Banana.hbm.xml
<class name="Banana" table="bananas" lazy="true">
<id name="Id">
<generator class="increment" />
</id>
<property name="Name" />
<many-to-one name="Monkey" column="Id" cascade="all" />
</class>
答案 0 :(得分:3)
参数索引超出范围错误是由于您的映射。您已将Id映射为关系中的主键和外键。
答案 1 :(得分:1)
子映射(Banana)不需要具有cascade属性。如果一个香蕉被删除,猴子可能还有其他香蕉,但是当猴子被改变时,它的所有香蕉应该相应地改变,所以只有猴子需要具有级联属性
答案 2 :(得分:1)
为了将来参考,您还应该包含数据库模式以解决此类问题,因为在不知道模式的情况下验证映射文件可能很困难。
我的猜测是你搞砸了你的外键。你说这个关系是一对多的,所以这意味着Banana有一个猴子表的外键,对吗?此外键列的标准命名是MonkeyID,这在您的映射中似乎缺少 - 所有列名称似乎都是ID。 James Ide在类似的行上回答,然后你说“Id是两个表中主键列的名称。我的关系映射应该是什么样的?” - 实际上,两个表上的主键列名称都是Id非常好,但仍然没有描述关系。正如我上面提到的,你需要一个外键用于关系。
一旦你修复了你的关系,你会发现级联问题会自行解决。人们通常想要从级联中获取的行为是从父级到子级的级联删除,但反之亦然,在这种情况下,您可能希望在多对一元素而不是级联上使用cascade =“save-update” = “所有”。
最后,作为一个无耻的插件,你考虑过尝试Fluent NHibernate吗?您可能会发现它比hbm xml语法更容易学习。