繁体   English   中英

Spring Data JPA OneToMany分页FetchType子选择

[英]Spring Data JPA OneToMany paging FetchType subselect

使用Spring Data JPA(当前为4.0.8)和Hibernate(当前为4.2.16)时,我很难在进行分页以继承JPA OneToMany列表的子选择命中时遇到问题。 在内部列表中,子选择选择所有要与主要元素组合的元素,而不仅仅是给定页面的元素。

例如:

JPA主要实体:

@Entity
@NamedQuery(name="Message.findAll", query="SELECT m FROM Message m")
public class Message implements Serializable {
...
//uni-directional many-to-one association to Message_Review
@OneToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
@JoinColumn(name="message_id", referencedColumnName="message_id", insertable=false, updatable=false)
@Fetch(FetchMode.SUBSELECT) 
private Set<Message_Review> messageReviews;

生成以获取JPA实体的主要列表的SQL是这样的:

SELECT TOP ? MESSAGE0_.MESSAGE_ID AS MESSAGE_1_0_, MESSAGE0_....... AND NOT (EXISTS (SELECT MESSAGEREV1_.MESSAGE_ID, MESSAGEREV1_.......))

在JPA实体的基本列表之后,Spring Data JPA(或Hibernate)然后查询OneToMany列表(按@ FetchMode.SUBSELECT)。 它这样生成SQL:

SELECT messagerev0_.message_id as message_2_0_1_, 
.....
where messagetop0_.message_id in 
(select message0_.message_id 
from .......
)

请注意,OneToMany命中的内部选择没有与之关联的TOP。 因此,它将撤回所有消息审阅(而不只是JPA将需要进行匹配的相关审阅)。 通常,这不是什么大问题,但是在OneToMany列表中有相当大的数据集的情况下,当给定页面只需要很小的子集时,有效负载可能会从数据库返回数百万个项目。

关于在使用@ FetchMode.SubSelect限制SQL命中次数时如何使分页携带到JPA实体中的OneToMany列表的任何想法?

您好,当您进行子选择读取时,这是非常正常的行为。 这就是应该的样子。 如果您想要更多可滚动的行为,可以使用@BatchSize(size = 5)批注,其中的大小告诉您一次将获取多少个集合。

因此,假设您有一个类似于“类别->项目关系”的内容,您可以执行以下操作:

从类别中选择*

然后您开始遍历类别。 当您访问项目时,它将返回5个相关集合。 不仅针对您浏览过的类别,而且针对接下来的5。

查询fir Item将如下所示:

从(1,2,3,4,5)中的categoryID中选择*

在我看来,您需要将@BatchSize与FetchType.Select结合使用。

我的解释不是很好,因此我也向您发送了一个链接。 请注意,Subselect的使用非常早。 http://www.mkyong.com/hibernate/hibernate-fetching-strategies-examples/

BatchSize与Subselect的优缺点:

批处理大小越大,内存消耗越大,您需要的CPU就越多。 我想将批量大小保持为低对于设备资源有限的设备是有好处的。 如果您打开Hibernate教程,则会看到性能调整一章中描述了@BatchSize。 与“子选择”策略相同,此暗示是子选择在大型数据集上可能非常繁重。 在这方面,就N + 1选择问题而言,使用BatchSize是一个很好的折衷方案,同时保持较低的内存消耗。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM