2016-07-07 3 views
1

스프링 데이터 JPA (현재 4.0.8)와 최대 절전 모드 (현재 4.2.16)에서 JPA OneToMany 목록의 subselect 히트 수를 넘기기 위해 페이지 매김을 얻는 데 문제가 있습니다. 내부리스트에서, subselect는 주어진 페이지에 대한 것뿐만 아니라 main과 결합 할 모든 요소를 ​​선택합니다.스프링 데이터 JPA OneToMany 페이징 FetchType subselect

메인 JPA 엔티티 : 예

는의베이스에서 후

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

:

는 SQL은 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 엔티티 인 Spring Data JPA (또는 Hibernate)는 (@ FetchMode.SUBSELECT에 따라) OneToMany리스트를 질의한다. 다음과 같이 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 목록으로 가져 오는 방법에 대한 아이디어가 있습니까?

답변

0

안녕하세요 이것은 Subselect 가져 오기가있을 때 매우 정상적인 동작입니다. 이것은 그것이 있어야하는 방법입니다. 스크롤 가능한 동작을 원할 경우 @BatchSize (size = 5) 주석을 사용할 수 있습니다. 여기서 크기는 한 번에 가져올 수있는 컬렉션 수를 알려줍니다.

그래서 당신은 카테고리와 같은 뭔가를 말할 수 -> 항목 관계와 당신이 할 : * 종류

에서

는 다음 카테고리를 반복

시작

. 항목에 액세스하면 관련 컬렉션 5 개가 반환됩니다. 뿐만 아니라 당신은 모양을 통해하지만 다음 5

쿼리 전나무 항목에 대한 탐색 한 범주에 대한 :

선택 * 항목에서 어디에 카테고리 ID에서 (1,2,3,4,5)

제 생각에는 FetchType.Select와 함께 @BatchSize가 필요합니다.

설명이 좋지 않아 링크도 보내드립니다. Subselect는 매우 초기에 사용됩니다. 부속 대 http://www.mkyong.com/hibernate/hibernate-fetching-strategies-examples/

장점과 BatchSize에서의 단점 :

더 큰 배치 크기가 더 큰 메모리 소비, 당신이 필요로하는 더 많은 CPU. 배치 크기를 낮게 유지하는 것이 제한된 리소스가있는 장치에 적합하다고 생각합니다. Hibernate 튜토리얼을 열면 @BatchSize가 성능 튜닝 챕터에 설명되어 있음을 알 수 있습니다. Subselect 전략과 마찬가지로이 옵션을 사용하면 대용량 데이터 세트에 대해 subselect가 매우 무거울 수 있습니다.이 점에서 BatchSize 사용은 N + 1 선택 문제와 관련하여 좋은 절충안이며 동시에 메모리 소비를 낮게 유지합니다.

+0

나는 이것이 내가 누락 된 것이라고 생각한다. 엔터티의 BatchSize 설정의 단점은 무엇입니까? (당신이 EAGER 초기화를 사용하고 있다면, 그것들이 이유 때문에 "1"로 디폴트한다고 가정)? – LetsBeFrank

+1

일괄 처리 크기가 클수록 메모리 사용량이 많을수록 더 많은 CPU가 필요합니다. 배치 크기를 낮게 유지하는 것이 제한된 리소스가있는 장치에 적합하다고 생각합니다. Hibernate 튜토리얼을 열면 @BatchSize가 성능 튜닝 챕터에 설명되어 있음을 알 수 있습니다. Subselect 전략과 마찬가지로이 옵션을 사용하면 대용량 데이터 세트에 대해 subselect가 매우 무거울 수 있습니다. 이 점에서 BatchSize 사용은 N + 1 선택 문제와 관련하여 좋은 절충안이며 동시에 메모리 소비를 낮게 유지합니다. –