假设我有实体A,B,C,每个A有很多B和C实体。我想根据一些criterea来查询A个实体的加载,我知道我将访问每个A返回的所有B和C实体。
像select a from A as a join fetch a.b join fetch a.c
这样的东西一开始似乎有意义,但如果B和C实体的数量很大,这会产生巨大的产品。将此扩展到另一个关联实体会使查询完全不合理。
如果我将JPA留给自己的设备,当我想访问B和C实体时,我最终会选择n + 1。
我认为我要做的是查询A连接提取B,然后连接提取C,但这不起作用,因为它给了我两个List<A>
结果,每个结果只有一半信息。
这是一个非常简单的SQL查询,我很失望没有一种明显的方法来处理这个问题。我错过了什么吗?
提供商是toplink essentials
答案 0 :(得分:1)
JPA至少应该提到对象。事实上,你并没有告诉我你不会充分利用JPA。
如果您有遗留架构,并且对象模型没有意义,那么您可能不应该使用JPA。
JPA并不打算替代SQL。它解决了对象关系不匹配问题。如果您没有对象,只需下拉到JDBC和SQL。
我不知道你的表代表什么,但是如果你正在考虑对象,你应该谈论1:m和m:n关系。一旦你有了那些,你可以使用缓存,懒惰和渴望获取来优化填充对象。
更新:编写查询,以便每个产品的选项和价格列表为1:m关系并进行急切提取。这将避免(n + 1)问题。
你怎么能说关系和热切的提取在这里没有帮助?
尝试表达对象中的关系,让JPA向您展示它生成的SQL,并将其与您编写的内容进行比较。如果它是令人满意的,那就去吧。如果没有,请下拉到JDBC,看看能否做得更好。
答案 1 :(得分:0)
我想知道为什么你说这在SQL术语中非常简单。你不也有笛卡儿产品吗?
使用JPA的Hibernate提供程序,您提到的选项有效:
查询连接提取B,然后是连接提取C
你有两个相同值的列表,你只使用一个,它很好(你只需要左边连接)。
在Hibernate中,您还可以要求在第二个查询中获取丢失的数据。
使用fetch="subselect"
。
请参阅https://www.hibernate.org/315.html
更新:
在java中,您也可以手动执行此操作。
这也会有很好的表现。
如果您多次运行此需求,您可以编写一个参数化方法来为您执行此操作,因此您只需编写一次代码。
正如原始海报评论的那样,您需要在修改它们之前从entityAs分离所有A实体,以确保不会向数据库发送更新......