【问题标题】:JPA fetching one to manyJPA 获取一对多
【发布时间】:2012-04-12 21:06:39
【问题描述】:

我有以下实体:事件和属性。一个事件可以有很多属性。

我遇到的问题是,我似乎找不到在单个 SQL 查询中返回事件及其属性的查询。我可能有数百万个需要迭代的事件,并且出于明显的性能原因,我不想延迟加载它们。

我尝试在查询中使用 fetch,但它会为每个属性返回一个事件。即,如果一个事件有 2 个属性,它将返回 2 个事件,每个事件都有一个属性。

我想要的是一个具有 2 个属性的事件。

SELECT e FROM Event e LEFT JOIN FETCH e.attributes

如果我添加 DISTINCT 它可以工作,但它会创建一个独特的 SQL 查询,这在大型数据集上非常慢。

public class Event {
  @OneToMany(mappedBy = "event", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
  public Set<Attribute> getAttributes(){}
}

public class Attribute {
    @ManyToOne(cascade=CascadeType.ALL)
    @JoinColumn(name = "event_id", nullable = false)
    public Event getEvent() {
        return event;
    }
}

解决方案

我找不到 JPA 解决方案。相反,我将 EntityManager 解包到 Hibernate 会话,并按照@milkplusvellocet 的建议使用标准的结果转换器。这将检索不同的根实体,而无需创建不同的 SQL 查询。

Session session = em.unwrap(Session.class);
Criteria criteria = session.createCriteria(Event.class);
criteria.setFetchMode("attributes", FetchMode.JOIN);

criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);  

需要注意的一点是,我尝试从展开的会话中使用 HQL。我将 DISTINCT 添加到查询中,并将结果转换器设置为 DISTINCT_ROOT_ENTITY,类似于上面的标准解决方案。这样做仍然创建了一个独特的 SQL 查询。

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    您需要ResultTransformer

    尝试以下 HQL:

    SELECT DISTINCT e FROM Event e LEFT JOIN FETCH e.attributes
    

    这相当于在条件查询中使用CriteriaSpecification.DISTINCT_ROOT_ENTITY

    【讨论】:

    • 当我添加 DISTINCT 时,它正在创建一个非常慢的不同 sql 查询(选择不同的 event0_.id 作为 ...)。不同的是整个结果已经不同但检查很慢......我没有看到使用 JPA 访问 ResultTransformer 的选项。
    • 你解决了吗?如果没有尝试初始化 DistinctRootEntityResultTransformer 并将 HQL 中的结果传递给它的 transformList(List) 方法。
    • 是的,我添加了问题的解决方案。由于某种原因,HQL 仍在生成不同的查询,但使用休眠条件并设置结果转换器完成了这项工作。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 2021-10-14
    相关资源
    最近更新 更多