【问题标题】:JPA 2.1 Entity Graph returns duplicated resultsJPA 2.1 实体图返回重复的结果
【发布时间】:2015-01-26 00:28:52
【问题描述】:

我开始使用 JPA 2.1 中的新实体图功能来指定必须加载的惰性集合。 考虑以下类:

@Entity
@NamedQueries({
    @NamedQuery(name="findWithFilterAttr","select a from A a where a.filterAttribute like :filter")
})
@NamedEntityGraphs({
@NamedEntityGraph(name = "graph.childs", attributeNodes = @NamedAttributeNode("childs"))})
public class A{
  @Id
  private long id;
  @OneToMany(mappedBy="parent")
  private List<B> childs;
  private String filterAttribute;
}
@Entity
public class B{ 
  @Id
  private long id;
  @ManyToOne
  private A parent;
}

当我执行命名查询以获取带有实体图提示的 A 实体列表时,我得到一个包含重复 A 实体的集合。 如何只加载 A 实体一次。

我正在使用:

  • 休眠 4.3.5
  • 野蝇 8.1

【问题讨论】:

    标签: hibernate jakarta-ee jpa entitymanager wildfly


    【解决方案1】:

    我终于解决了这个问题,我将 DISTINCT 添加到命名查询中,现在一切正常...... 导致该错误的原因是,当 JPA Provider 找到实体图提示时,它会创建与子表的 LEFT JOIN。 没有实体图的原始查询:

    11:55:28,950 INFO  [stdout] (default task-23) Hibernate: 
    11:55:28,950 INFO  [stdout] (default task-23)     select
    11:55:28,951 INFO  [stdout] (default task-23)         entitya0_.id as id1_0_0_,
    11:55:28,951 INFO  [stdout] (default task-23)         childs1_.id as id1_1_1_,
    11:55:28,951 INFO  [stdout] (default task-23)         entitya0_.filter as filter2_0_0_,
    11:55:28,951 INFO  [stdout] (default task-23)         childs1_.parent_id as parent_i2_1_1_,
    11:55:28,951 INFO  [stdout] (default task-23)         childs1_.parent_id as parent_i2_0_0__,
    11:55:28,951 INFO  [stdout] (default task-23)         childs1_.id as id1_1_0__ 
    11:55:28,951 INFO  [stdout] (default task-23)     from
    11:55:28,951 INFO  [stdout] (default task-23)         EntityA entitya0_ 
    11:55:28,951 INFO  [stdout] (default task-23)     left outer join
    11:55:28,952 INFO  [stdout] (default task-23)         EntityB childs1_ 
    11:55:28,952 INFO  [stdout] (default task-23)             on entitya0_.id=childs1_.parent_id 
    11:55:28,952 INFO  [stdout] (default task-23)     where
    11:55:28,952 INFO  [stdout] (default task-23)         entitya0_.filter like ?
    

    使用不同的实体图进行查询:

    11:57:25,051 INFO  [stdout] (default task-24) Hibernate: 
    11:57:25,052 INFO  [stdout] (default task-24)     select
    11:57:25,052 INFO  [stdout] (default task-24)         distinct entitya0_.id as id1_0_0_,
    11:57:25,052 INFO  [stdout] (default task-24)         childs1_.id as id1_1_1_,
    11:57:25,052 INFO  [stdout] (default task-24)         entitya0_.filter as filter2_0_0_,
    11:57:25,052 INFO  [stdout] (default task-24)         childs1_.parent_id as parent_i2_1_1_,
    11:57:25,052 INFO  [stdout] (default task-24)         childs1_.parent_id as parent_i2_0_0__,
    11:57:25,052 INFO  [stdout] (default task-24)         childs1_.id as id1_1_0__ 
    11:57:25,052 INFO  [stdout] (default task-24)     from
    11:57:25,052 INFO  [stdout] (default task-24)         EntityA entitya0_ 
    11:57:25,052 INFO  [stdout] (default task-24)     left outer join
    11:57:25,052 INFO  [stdout] (default task-24)         EntityB childs1_ 
    11:57:25,052 INFO  [stdout] (default task-24)             on entitya0_.id=childs1_.parent_id 
    11:57:25,052 INFO  [stdout] (default task-24)     where
    11:57:25,052 INFO  [stdout] (default task-24)         entitya0_.filter like ?
    

    【讨论】:

    • 非常感谢您发布您的解决方案!这也适用于名为 Queries 的 JPA。见:this SO post
    • 你能写出你是如何在查询中添加不同的吗?
    【解决方案2】:

    一个小的补充。

    我和你有同样的问题。 我认为这种行为是出乎意料的,可能是hibernate的一个缺陷。 不需要指定 distinct,因为直接在 JPQL 查询中指定的提取就是这种情况。

    由于实施的限制,您的解决方案是一种解决方法。 通过检查代码(list()方法中needsDistincting标志的计算,在grepcode可用),有2个解决方案:

    • 为查询添加限制
    • 使用不同的

    【讨论】:

    • 注意:这是一个纯粹的休眠问题,这里没有 Wildfly。您应该删除标签。
    猜你喜欢
    • 2016-07-02
    • 2018-06-16
    • 2019-03-16
    • 2015-01-18
    • 2020-09-21
    • 2018-01-16
    • 2013-03-04
    • 2014-03-13
    • 2020-09-09
    相关资源
    最近更新 更多