【问题标题】:StackOverflowError when retriving ManyToMany join table with Java EJB 3使用 Java EJB 3 检索多对多连接表时出现 StackOverflowError
【发布时间】:2011-05-06 14:56:46
【问题描述】:

我的 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());

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

我已经为每个类覆盖了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 生成的,我已经选择了要在其中使用的主键,其他类都使用相同的东西。

【问题讨论】:

  • 我会推荐 jpa 或 hibernate 标签而不是其他一些标签(例如,stackoverflowerror 或 ejb)。
  • @bkail 你能解释一下为什么吗?我已经使用 EJB3 注释 (JPA) 4 年了,没有任何问题。
  • @Augusto 我的意思是 stackoverflow.com 问题标签; JPA 或 hibernate 专家可能会错过当前标签集的问题。
  • 好的,谢谢,我已经改了。

标签: java hibernate jpa jakarta-ee ejb


【解决方案1】:

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

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

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

*总有办法

【讨论】:

  • 感谢您的回复,我认为这不是数据库大小的问题,目前我正在使用 1 次爬网和 6 个页面和 6 次更改对其进行测试。你说的树摇摇晃晃到底是什么意思?这会涉及更改和页表的组合吗?
  • Ups,这是不同的。你能证明你没有循环关系吗?例如PageX包含ChangeX; ChangeX 有 CrawlX,CrawlX 包括 ChangeX。
  • 我相信是这样的。就目前而言,只有一次爬网,因此所有更改都将存储该爬网,并且爬网将存储所有更改。我虽然休眠会检测到循环关系并且不会陷入循环。有没有办法解决这个问题?我映射多对多关系错了吗?我是否遗漏了一些注释?
  • 我不认为它适用于一对多的关系,但它适用于多对多的关系。这并不理想,如果您将关系提取到另一个表,您可以欺骗休眠并将关系映射为多对多。哦,你能发布哈希码和等号吗?因为如果它们不正确,可能会发生这种情况。
  • 我已经使用 hashcode 和 equals 方法编辑了原始帖子。提取关系究竟会涉及什么?
猜你喜欢
  • 2018-05-17
  • 1970-01-01
  • 2020-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
相关资源
最近更新 更多