使用Java EJB 3检索ManyToMany连接表时的StackOverflowError

时间:2011-05-06 14:56:46

标签: java hibernate jpa java-ee ejb

我的EJB3应用程序有以下实体映射,它映射多对多关系:

@Entity
Crawl{
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.crawl")
    public List<Change> changes;
}

@Entity
Change{
    @EmbeddedId
    ChangePK pk;
    @Temporal(javax.persistence.TemporalType.DATE)
    Date changeDate;
}

@Embeddable
ChangePK{
    @ManyToOne
    Crawl crawl;

    @ManyToOne
    Page page;
}

@Entity
Page{
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.page")
    List<Change> changes;
}

我正在尝试获取与抓取相关的所有更改,并使用以下日期对它们进行排序:

this.entityManager
    .createQuery("SELECT c FROM Change c WHERE 
                  c.pk.crawl.id = :id 
                  ORDER BY c.changeDate DESC")
   .setParameter("id", crawl.getId());

这给了我一个堆栈溢出错误。我相信急切的提取可能与它有关,但在其他所有情况下,我希望更改加载了爬行,如果我将获取类型更改为lazy,它将在我的应用程序的其余部分中导致很多问题。

我已经为每个类重写了hashCodeequals方法。

编辑:

hashcodeequals代码:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + id;
    return result;
}

@Override
public boolean equals(Object obj) {
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Crawl other = (Crawl) obj;
    if (id != other.id)
        return false;
    return true;
}

这些是由Eclipse生成的,我选择了要在其中使用的主键,其他类都使用相同的东西。

1 个答案:

答案 0 :(得分:0)

如果对象树的整个树很大,那么没有办法 *来避免堆栈溢出,因为hibernate递归地解析了依赖关系,这对于99.9%的情况是可以的(在8年的使用中) hibernate,这是我第一次看到这个错误。)

解决此问题的另一种方法是增加堆栈大小,但这会增加所有应用程序线程的大小(这可能不是很好)。例如,您可以在运行JVM时添加选项-Xss1m,并获得1mb的堆栈大小。 (默认堆栈大小因平台而异,但我认为通常为512k)

另一个替代方案是更改映射,但我认为所有都包括对表进行非规范化。 一种选择是展平树,因此给定特定的爬网,您可以使用一个查询检索爬网的所有子项。在这种情况下,集合Crawl.changes包含爬网的所有子项,孙子等。

* 始终有一种方式