我有一个简单的对象关系,我希望坚持使用hibernate。
基本上,它是一个包含一系列儿童的父母。我想做的就是加载父项(如果存在),否则创建它,添加元素并保存它。
这是在GWT环境中完成的,所以我将ChildDTO传递给这个方法,这个方法基本上只是一个非持久版的Child类(与gwts RPC序列化不兼容)。
public Integer testHibernate(Integer parentId, ChildDTO[] test) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Parent model;
if(parentId == null) {
// if the parentId is null, create new instance
model = new Parent );
}
else {
model = (Parent) hib.load(Parent.class, dto.getId());
}
model.setName("dummy name");
for(int i = 0; i < test.length) {
model.addChild(new Child(test[i].getId(), test[i].getName()));
}
hib.save(model);
hib.getTransaction().commit();
return model.getId();
}
是的,这适用于创建没有孩子的新父母。如果我只是将一个孩子添加到现有父级,它也可以正常工作。但是,如果我添加了多个子节点,我会从hibernate中收到“无法插入”错误。
此外,如果我尝试只添加一个孩子,则添加已添加一个孩子的已存在父母。我得到一个“具有相同标识符值的不同对象已经与会话关联”错误。
其他问题。当只插入一个子节点时,在空父节点上,hibernate会执行以下操作:
Hibernate: insert into Child(ChildId, ChildName) values (default, ?)
Hibernate: update Parent set ChildId=? where ChildId=?
有什么更新? :S
答案 0 :(得分:2)
但是,如果我添加了多个孩子,我会收到“无法插入” 来自休眠的错误。
从似乎的问题看,父子关系已经设置为一对一而不是一对多。首先确保你的hibernate配置文件中的内容是正确的。
<set name="children">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
另外,如果我尝试只将一个孩子添加到已存在的父母, 已添加一个孩子。我得到了一个“与...不同的对象 相同的标识符值已与会话相关联“ 错误。强>
在以下代码段中,您只需使用Id保存子项,而不检查它是否已存在。请记住,Child
也作为一行存储在数据库中。所以你需要检查数据库中是否存在该对象。
for(int i = 0; i < test.length) {
model.addChild(new Child(test[i].getId(), test[i].getName()));
}
当只插入一个子节点时,在空父节点上,hibernate会执行 以下强>
这是合乎逻辑的,第一个INSERT
语句对应于Child
对象的新行。第二个UPDATE
语句对应于在Parent
和Child
个对象之间建立链接。
您可以通过设置inverse
关系来优化此操作。在这种情况下,Child
表存储parent_id,因此产生一个INSERT
语句而不是两个语句。
<set name="children" inverse="true">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
请参阅Hibernate文档中的此链接,该链接清楚地说明如何设置和实施Parent-Child
关系:http://docs.jboss.org/hibernate/core/3.3/reference/en/html/example-parentchild.html#example-parentchild-bidir