Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.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 JPA/Hibernate内存不足异常_Java_Spring_Hibernate_Jpa_Persistence - Fatal编程技术网

Java JPA/Hibernate内存不足异常

Java JPA/Hibernate内存不足异常,java,spring,hibernate,jpa,persistence,Java,Spring,Hibernate,Jpa,Persistence,我最近将一个使用本机Hibernate实体和会话管理的项目转移到Spring上,使用注释驱动的依赖项注入和事务管理 我有这样一个实体结构: @Entity @Table(name = "PARENT",uniqueConstraints=@UniqueConstraint(columnNames={"parentName"})) public class Parent implements Serializable, { static final long serialVersionUI

我最近将一个使用本机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;
}
@实体
@表(name=“PARENT”,uniqueConstraints=@UniqueConstraint(columnNames={“parentName”}))
公共类父级实现可序列化{
静态最终长SerialVersionId=1L;
@身份证
私有int-id;
@OneToMany(mappedBy=“parent”,fetch=FetchType.EAGER,cascade=CascadeType.ALL)
private Set child=new HashSet();
}
@实体
@表(name=“CHILD”,uniqueConstraints=@UniqueConstraint(columnNames={
“childName”、“parent_id”})
@SequenceGenerator(name=“CHILD_SEQ”,allocationSize=1,sequenceName=“CHILD_SEQ”)
公共类子级实现可序列化{
静态最终长SerialVersionId=1L;
@身份证
@GeneratedValue(策略=GenerationType.SEQUENCE,generator=“CHILD_SEQ”)
私有int-id;
私有字符串childName=“”;//$NON-NLS-1$
@许多酮
@JoinColumn(name=“parent\u id”)
私人家长;
}
下面是发生的情况

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

    public List<Parent> getParents() {
        return em.createQuery("from Parent",Parent.class).getResultList();
    }
    
    public List getParents(){
    返回em.createQuery(“从父级”,父级).getResultList();
    }
    
  • 然后我尝试获取每个子对象,应用程序冻结,我的电脑速度变慢,几个小时后,我出现内存不足异常

    public List<Child> getChildren() {
        return em.createQuery("from Child",Child.class).getResultList();
    }
    
    public List getChildren(){
    返回em.createQuery(“从子级”,子级).getResultList();
    }
    
我已经查看了生成的SQL,对于第一种方法,它似乎在逻辑上分解了对单个对象集的调用,在接下来的几秒钟里,它似乎构造了一个怪物大小的查询,我无法真正理解,并且该查询似乎没有返回,尽管我无法真正判断


我无法理解的是,为什么对父对象的查询工作得如此之快,并为我提供了每个对象,但子查询却中断了

这可能是内存泄漏导致的。 您可以使用增加堆空间

-Xms设置初始Java堆大小

-Xmx设置最大Java堆大小

但是,最好知道java.lang.OutOfMemoryError的原因:java堆空间。使用分析器可以帮助您确定是什么影响了堆的大小。 如果您使用的是Netbeans,那么可以使用
或者查找与IDE兼容的探查器。

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

另一方面,当您从子级开始时,Hibernate必须首先为每个子级获取父级。这意味着一个与父表的联接。但是,这些家长有孩子,因此我们必须再次加入子表才能找到他们


您的类不完整,缺少父名称,并且您提到了其他集合。如果其他集合也很急切,则必须使用第一个子级和第二个子级的联接来获取它们,每个集合再添加两个联接。这是一个非常复杂的查询

您是否可以共享持久化逻辑?因为存在格式问题。请尝试em.persist而不是merge,因为持久化对象无法管理,如果这不起作用,请共享调用saveChild()的代码。
FetchType.EAGER的任何特定原因?除非有很好的理由,否则它应该是
FetchType。LAZY
作为
EAGER
会有加载非常大的对象图的风险,这可能会导致
OutOfMemory
异常。那么数据库中到底有多少子级?在返回前调用em.merge()时会发生错误,任何内存问题都可能是Hibernates问题,而不是我应该或可能必须解决的问题。延迟抓取和手动控制何时初始化这些集合是有效的。但我最初的问题是,当从使用带手动控制的本机hibernate转到JPA/Spring时,即使所有数据结构都相同,所有函数都执行相同的操作,问题还是出现了。因此,看起来本机hibernate调用实际上比JPA的实现更好地处理这些循环,这让我感到惊讶。我相信Hibernate默认为连接(fetch),这就是问题所在。我认为EclipseLink会为每一位家长做一个细分,所以不会有问题。如果需要控制行为,Hibernate允许您指定
FetchMode