JPA / Hibernate Out of Memory异常

时间:2017-04-13 08:29:31

标签: java spring hibernate jpa persistence

我最近将一个使用本机Hibernate实体和会话管理的项目移到了Spring上,注释驱动的依赖注入和事务管理。

我有一个像这样的实体结构:

@Entity
@Table(name = "PARENT",uniqueConstraints=@UniqueConstraint(columnNames={"parentName"}))
public class Parent implements Serializable, {
    static final long serialVersionUID = 1L;

    @Id
    private int id;


    @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<Child> child = new HashSet<Child>();
}



@Entity
@Table(name = "CHILD", uniqueConstraints = @UniqueConstraint(columnNames = {
        "childName", "parent_id" }))
@SequenceGenerator(name = "CHILD_SEQ", allocationSize = 1, sequenceName = "CHILD_SEQ")
public class Child implements Serializable {

    static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "CHILD_SEQ")
    private int id;
    private String childName = ""; //$NON-NLS-1$

    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;
}

这里发生了什么。

  • 我得到所有包含子对象列表的父对象。这很快,我在调试器的内存中有完整的对象树我可以看到每个Child对象都正确加载。

    public List<Parent> getParents() {
        return em.createQuery("from Parent",Parent.class).getResultList();
    }
    
  • 然后我尝试获取每个Child对象并且应用程序冻结我的PC速度变慢,几个小时后我得到Out on memory异常。

    public List<Child> getChildren() {
        return em.createQuery("from Child",Child.class).getResultList();
    }
    

我已经查看了生成的SQL,对于第一种方法,它似乎逻辑上将调用分解为单个对象集,并且在几秒钟内它似乎构建了一个怪物大小的查询,我无法真正遵循并且该查询似乎没有返回,但我无法说出来。

我无法理解的是,为什么对父项的查询工作如此之快并且给了我每个单独的对象,但子查询只是中断了。

2 个答案:

答案 0 :(得分:3)

当你从父母开始时,Hibernate可以读取所有父母(简单)并加入子表(再次,简单)。每个孩子只有一个父母,这是我们加入的父母,所以这就足够了。虽然整个数据库都被读入内存,因为它很小也没有问题。

另一方面,当你从孩子开始时,Hibernate必须首先为每个孩子取一个父母。这意味着与父表的一个连接。但是,这些父母有孩子,所以我们必须再次与孩子桌一起找到它们。

您的课程不完整,缺少家长姓名,您提及其他馆藏。如果其他集合也很渴望,则必须使用第一个子级别和第二个子级别的连接来获取,每个集合再添加两个连接。这使得查询非常复杂!

答案 1 :(得分:-1)

可能是内存泄漏造成的。 您可以使用。

增加堆空间

-Xms<size> set initial Java heap size

-Xmx<size> set maximum Java heap size

http://javarevisited.blogspot.com.ng/2011/09/javalangoutofmemoryerror-permgen-space.html

但是,了解java.lang.OutOfMemoryError的原因是什么很好:Java堆空间。使用分析器可以帮助您找出吃堆大小的内容。 如果您使用的是Netbeans,则可以使用https://profiler.netbeans.org/ 或者找到与IDE兼容的分析器。