스프링 데이터 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 목록으로 가져 오는 방법에 대한 아이디어가 있습니까?
나는 이것이 내가 누락 된 것이라고 생각한다. 엔터티의 BatchSize 설정의 단점은 무엇입니까? (당신이 EAGER 초기화를 사용하고 있다면, 그것들이 이유 때문에 "1"로 디폴트한다고 가정)? – LetsBeFrank
일괄 처리 크기가 클수록 메모리 사용량이 많을수록 더 많은 CPU가 필요합니다. 배치 크기를 낮게 유지하는 것이 제한된 리소스가있는 장치에 적합하다고 생각합니다. Hibernate 튜토리얼을 열면 @BatchSize가 성능 튜닝 챕터에 설명되어 있음을 알 수 있습니다. Subselect 전략과 마찬가지로이 옵션을 사용하면 대용량 데이터 세트에 대해 subselect가 매우 무거울 수 있습니다. 이 점에서 BatchSize 사용은 N + 1 선택 문제와 관련하여 좋은 절충안이며 동시에 메모리 소비를 낮게 유지합니다. –