【问题标题】:What is the best optimized way to select many entities with subentities in JPA?在 JPA 中选择许多具有子实体的实体的最佳优化方法是什么?
【发布时间】:2011-03-31 04:29:28
【问题描述】:

假设我们有:

@Entity public class Order {
  @Id private int id;
  @OneToMany(mappedBy="order") private List<Item> items;
  ...
}

@Entity public class Item {
  @Id private int id;
  @ManyToOne private Order order;
  ...
}

假设有 10.000 个订单,每个订单有 20 件商品。

我们需要反复思考所有订单及其所有项目。 在 JPA 中最好的方法是什么?

我的问题是,如果我只是迭代以下元素:

for (Order order: em.createTypeQuery("select o from Order o", Order.class).getResultList()) {
    report.printOrder(order);
    for (Item item: order.getItems()) {
        report.printOrderItem(item);
    }
}

这将导致 10.001 个 sql 查询: 1次:从订单中选择* 10.000 次:select * from item where order_id = ?

有什么办法可以优化吗?两个查询?一个查询?

(我们正在使用 EclipseLink)

谢谢。

【问题讨论】:

    标签: java optimization jpa eclipselink one-to-many


    【解决方案1】:

    您可以使用join fetch(这也需要distinct,因为join fetch 具有join 语义):

    select distinct o from Order o join fetch o.items
    

    【讨论】:

    • 谢谢。这也很有帮助。但是,在我测试之后:join fetch 将此查询转换为“select distinct o.*, i.* from Order o, Item i where o.id = i.orderId”,这意味着对于每个项目,结果集将传输所有订单的字段。在某些情况下,这会导致大量开销。
    【解决方案2】:

    您可能还需要考虑值为“o.items”的 EclipseLink 查询提示“eclipselink.batch”。这会产生两个查询,但比一次大型连接查询更有效。

    【讨论】:

    • 谢谢。我刚刚对其进行了测试并发现:1)您可以使用多个此类提示,例如: q.setHint("eclipselink.batch", "t.testSurveys"); q.setHint("eclipselink.batch", "t.testDefects"); 2) EclipseLink 以一种懒惰的方式使用这个批处理提示。它发送秒查询以获取 o.items,不是立即,而是在您调用 first order.getItems() 之后。
    猜你喜欢
    • 2012-01-08
    • 2011-08-25
    • 1970-01-01
    • 2014-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    相关资源
    最近更新 更多