【问题标题】:Does hibernate allow to define the order of saving child elementshibernate是否允许定义保存子元素的顺序
【发布时间】:2016-11-09 21:20:03
【问题描述】:

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

假设我们已经提供了所有可能的父子关系,现在我们正在调用休眠会话的合并方法。我们这里面临的问题是,Child1Child2 之间的关联没有得到管理。它给出休眠异常并显示消息“不存在具有给定标识符的行”。这个错误是由于休眠插入父级然后插入Child2,然后插入Child1。理想情况下,它应该插入ParentChild1Child2。所以它可以管理Child1Child2之间的关联。

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

我们还从数据库中删除了与Child2 关联的Child1 的外键引用。但是hibernate会自动管理关系,所以它不起作用。

改变Parent类中定义的Children的插入顺序只有一个要求

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

代码片段:

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;
    }
}

【问题讨论】:

  • 问题恕我直言是合并方法。使用合并时,HIbernate 不能很好地工作。在处理分离的实体时,Hibernate 实际上并不能很好地工作。我的意思是,它具有此功能,并且在许多更简单的情况下可能会有所帮助。但它并没有真正摇滚。我们的项目中也有这个问题。然后我们将所有内容更改为使用 DTO。现在一切都变得更顺畅了。
  • 是的,我认为 DTO 也会很有用。您的核心逻辑应该代表域,当客户端(即网络)需要一些与域相比在视图上完全不同的数据时,然后使用数据传输对象来处理这种情况。
  • 如何使用 DTO 为相同的父子场景更新数据库中的某些列?请问一下?

标签: hibernate hibernate-onetomany


【解决方案1】:

正如我在评论中所说,使用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);

【讨论】:

  • 我猜你的意思是saveOrUpdate()
猜你喜欢
  • 2010-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-29
  • 2015-04-21
  • 1970-01-01
  • 2013-07-29
相关资源
最近更新 更多