休眠是否允许定义保存子元素的顺序

时间:2016-07-07 13:59:09

标签: hibernate hibernate-onetomany

hibernate是否允许定义在POJO中执行定义为List的子元素的顺序。 假设我们有一个包含多个子项的Parent类(Child1Child2)。父和子之间的关联是OneToMany,它们被定义为列表。 我们在亲子之间有双向关系。 Child1Child2之间也存在ManyToOne关系。 Child2Child1具有ManyToOne关系,即Child2包含Child1的主键作为外键引用,并且它们都与Parent共享OneToMany关系。< / p>

让我们假设我们已经提供了所有可能的父子关系,现在我们正在调用hibernate session的merge方法。我们在这里遇到的问题是,Child1Child2之间的关联未得到管理。它给出了带有消息&#34的hibernate异常;没有给定标识符的行存在&#34;。由于hibernate插入父节点而导致此错误,然后它插入Child2然后插入Child1。理想情况下,它应该插入ParentChild1Child2。因此,它可以管理Child1Child2之间的关联。

理想情况下,类将在会话工厂中定义,或者在hibernate.cfg.xml文件中定义。这里我们试图改变XML中定义类的顺序。但结果却一样。

我们还从数据库中删除了与Child1关联的Child2的外键引用。但是hibernate会自动管理关系,因此无法解决问题。

只需要更改Parent

中定义的子项的插入顺序

请尽快提供建议/解决方案

代码段:

public class Parent{
    private List<Child1> child1;
    private List<Child2> child2;

    public Parent(){
        child1 = Collectionz.newArrayList();
        child2 = Collectionz.newArrayList();
    }


    @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "parent", orphanRemoval = true)
    @Fetch(FetchMode.SUBSELECT)
    public List<Child1> getChild1() {
        return child1;
    }

    public void setChild1(List<Child1> child1) {
        this.child1 = child1;
    }


    @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "parent", orphanRemoval = true)
    @Fetch(FetchMode.SUBSELECT)
    public List<Child2> getChild2() {
        return child2;
    }

    public void setChildren2(List<Child2> child2) {
        this.child2 = child2;
    }

}

public class Child1{
    private Parent parent;
    private Set<Child2> child2;

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="PARENT_ID")
    public PkgData getParent() {
        return parent;
    } 

    public void setParent(Parent parent) {
        this.parent = parent;
    }


    @OneToMany(cascade={CascadeType.ALL},fetch=FetchType.LAZY,mappedBy="child1")
    @Fetch(FetchMode.SUBSELECT)
    public Set<Child2> getChild2() {
        return child2;
    }
    public void setChild2(Set<Child2> child2) {
        this.child2 = child2;
    }

}


public class child2{
    private Parent parent;
    private Child1 child1;


    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="PARENT_ID")
    public PkgData getParent() {
        return parent;
    } 

    public void setParent(Parent parent) {
        this.parent = parent;
    }


    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="CHILD_1_ID")
    public Child1 getChild1() {
        return child1;
    }

    public void setChild1(Child1 child1) {
        this.child1 = child1;
    }
}

1 个答案:

答案 0 :(得分:0)

正如我在评论中所说,使用merge并不理想。

无论如何,你可以先把一些孩子合并来解决这个问题。

// sorry if this is not correct java, I'm a C# programmer
foreach(Child2 child2 in parent.Children2)
{
  session.merge(child2);
}
session.merge(parent);

顺便说一下,如果对象已经在会话中,则只需要merge。如果保证不是,请使用saveOrUpdate

session.saveOrUpdate(parent);