在加载父级时急切地获取子级

时间:2015-07-10 14:02:12

标签: java spring hibernate jpa spring-data-jpa

我使用Spring Data Jpa,Hibernate是提供者。

我有一个父类映射如下:

@Entity
@Table(name="parent")
public class Parent {

    private List<Child> childs;
    private List<AnotherChild> anotherChilds;

    @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
    public List<Child> getChilds() {
        return childs;
    }

    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY)
    public List<AnotherChild> getAntoherChilds() {
        return anotherChilds;
    }

}

和孩子:

@Entity
@Table(name="child")
public class Child {

    private Parent parent;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "column_name")
    public Parent getParent() {
        return patern;
    }

}

@Entity
@Table(name="another_child")
public class AnotherChild {

    private Parent parent;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "column_name")
    public Parent getParent() {
        return patern;
    }

}
  • 当我从数据库加载父项时,它不会加载列表 孩子马上和
  • 当我调用parent.getChilds()时,它返回 空值。
你能提一些建议吗?我错了吗?谢谢。

修改

经过一些研究,我意识到,当我只有一个孩子时,它会急切地加载(就像它应该的那样)。但是当我有多个孩子时,它并没有 - 即使它已被标记为FetchType.EAGER而另一个已被标记为FetchType.LAZY。

注意:如果我将两者标记为FetchType.EAGER,它会抛出MultipleBagFetchException:无法同时获取多个行李。

当我使用@Fetch(FetchMode.JOIN)注释它时发生了同样的事情

1 个答案:

答案 0 :(得分:2)

如果添加了实体注释,则parent.getChilds()不应该为空。当你执行Entity时,它会更好。

    @Entity 
    @Table(name="PARENT_TBL")
    public class Parent {
        //other fields
        @OneToMany(mappedBy = "parent",fetch = FetchType.LAZY,cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE},orphanRemoval = true)
        private List<Child> childs;
        //getter setter        
    }


    @Entity 
    @Table(name="CHILD_TBL")
    public class Child {
     //other fields
      @ManyToOne(fetch = FetchType.LAZY)
      @JoinColumn(name = "PARENT_ID")
      private Parent parent;
    //getter setter

 }

示例获取父查询;

public Parent getParent(long parentId) throws Exception {
   session = sessionFactory.openSession();
       Criteria cr = session.createCriteria(Parent.class, "parent");
        cr.setFetchMode('parent.childs', FetchMode.JOIN);
        cr.add( Restrictions.eq("parent.id", parentId));
        Parent parent = cr.uniqueResult();
        tx = session.getTransaction();
        session.beginTransaction();
        tx.commit();
    return parent;

EAGER加载集合意味着它们在获取父级时完全获取。因此,如果您有Parent并且它具有List,则在获取Parent时将从数据库中提取所有子项。

LAZY另一方面意味着只有在您尝试访问它们时才会获取List的内容。例如,通过调用parent.getChilds()。iterator()。在List上调用任何访问方法将启动对数据库的调用以检索元素。这是通过在列表(或集)周围创建代理来实现的。因此,对于您的惰性集合,具体类型不是ArrayList和HashSet。