Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 外键未存储在子实体中(一对多)_Java_Hibernate_Mapping_Annotations - Fatal编程技术网

Java 外键未存储在子实体中(一对多)

Java 外键未存储在子实体中(一对多),java,hibernate,mapping,annotations,Java,Hibernate,Mapping,Annotations,我对hibernate很陌生,偶然发现了这个问题,我找不到解决办法 在持久化父对象(与子对象具有一对多关系)时,此父对象的外键不存储在子表中 我的班级: Parent.java Test.java 公共类测试(){ 私人家长; public void setParentDao(ParentDao ParentDao){ this.parentDao=parentDao; } 私生子道; 公共无效setChildDao(ChildDao ChildDao){ this.childDao=paren

我对hibernate很陌生,偶然发现了这个问题,我找不到解决办法

在持久化父对象(与子对象具有一对多关系)时,此父对象的外键不存储在子表中

我的班级:

Parent.java Test.java
公共类测试(){
私人家长;
public void setParentDao(ParentDao ParentDao){
this.parentDao=parentDao;
}
私生子道;
公共无效setChildDao(ChildDao ChildDao){
this.childDao=parentDao;
}
test1(){
父项=新父项();
子项=新子项();
child.setChildId1(“a”);
child.setChildId2(“b”);
ArrayList子项=新的ArrayList();
添加(child);
父母、子女(子女);
父项。设置值(“值”);
parentDao.save(parent);//调用hibernate的currentSession.saveOrUpdate(实体)
}
test2(){
父项=新父项();
父项。设置值(“值”);
parentDao.save(parent);//调用hibernate的currentSession.saveOrUpdate(实体)
子项=新子项();
child.setChildId1(“a”);
child.setChildId2(“b”);
setParent(家长);
childDao.save();//调用hibernate的currentSession.saveOrUpdate(实体)
}
}

调用test1()时,两个实体都会写入数据库,但子表中的字段PARENT_ID保持为空

到目前为止,我唯一的解决方法是test2()——先持久化父对象,然后持久化子对象

我的目标是在一次调用中持久化父级及其子级,以在父级上保存()。 有什么想法吗?

问题是,在test1()中,在保存父对象之前先保存子对象。在test2()中,首先保存父对象,然后保存子对象,这是正确的,这也是它工作的原因

这样想吧。你能在父母出生之前出生吗?不,他们必须先存在,然后你才能存在。按照test2()中的操作,先装箱父对象,然后装箱子对象


如果需要,可以编辑parentDAO.save()以保存或更新任何引用的子级。这样,它们只需一次调用即可保存。

在保存父对象之前,它没有被分配ID。因此,当您首先保存子对象时,它没有要保存的外键。您希望像test2()一样执行此操作,但将其包装在事务中。看一看。我认为标题为“使用EJB/CMT进行事务划分”的部分可能正是您想要的。

您还可以向父级添加一个额外的方法,如

public void addChild(Child child) 
这是什么意思

    child.setParent(this);

我有一个很好的解决方案:D

mappedBy是指inverse=“true”。因此您必须inverse=“false”

试试看

@OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.ALL})//javax.persistent.CascadeType
@JoinColumn(name = "parent_id")//parent's foreign key
public Collection<Child> getChildren() {
    return children;
}
@OneToMany(fetch=FetchType.EAGER,cascade={CascadeType.ALL})//javax.persistent.CascadeType
@JoinColumn(name=“parent\u id”)//父项的外键
公共集合getChildren(){
返回儿童;
}
我希望它能正常工作

test1()中的主要问题是您没有在子对象中设置父对象。你应该说。。setParent(父)。 仅仅在parent中设置child并不意味着child知道parent。事实上,它的孩子谁拥有关系。因此,有必要在子对象中设置父对象。 对父级或子级调用saveorUpdate()的顺序无关紧要


test2()正在工作,因为您通过调用child.setParent()在子对象中设置了父对象。test1()中缺少此项。

感谢您的解释。我以为hibernate会处理这些操作。在查看test1()的日志和hibernate插入/更新时,先插入父级,然后插入子级。在我看来,hibernate应该足够“聪明”来获取Id表单,插入父项,然后将其分配给子项并执行插入。所以总结一下——在一个场景中,我想为一个父级插入50个子级,我必须为每个子级调用save()?你确定hibernate没有其他“自动”的方法吗?:)你可以在你的DAO中写一个函数来保存一个孩子的列表。我不认为这是真的。如果启用showsql,您可以看到首先保存父级,正如我在上面的注释中所解释的,在查看test1()的hibernate日志时,先插入父级,然后插入子级。所以hibernate应该足够聪明,能够从第一次插入中确定id并将其分配给第二次插入?很好,实现这个方法解决了我的问题。现在,我不再创建新数组,而是在创建新数组的地方调用parent.addChild(child)(如果需要),然后将父数组分配给子数组。现在,对父对象调用save()可以像我所希望的那样保存这两个实体。谢谢你的主意!非常感谢您抽出时间。你能告诉我们为什么hibernate在内部不关心这个问题吗?或者有没有办法把它交给hibernate呢?八十多年前,我还以为hibernate已经不存在了:-)我已经习惯了其他牧场(不一定更绿)。可能它已经改变了,但我想它会引起各种各样的歧义(我是谁的父母)我将如何在xml中做到这一点?
public void addChild(Child child) 
    child.setParent(this);
@OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.ALL})//javax.persistent.CascadeType
@JoinColumn(name = "parent_id")//parent's foreign key
public Collection<Child> getChildren() {
    return children;
}