합리적인 시간과 적절한 쿼리 횟수로 DB에서 매우 복잡한 개체를 완전히로드하는 데 문제가 있습니다.최대 절전 모드 : 복잡한 개체의 초기화
내 객체가 포함 된 엔티티을 많이 가지고, 각각의 개체가 다른 개체에 대한 참조를 가지고, 다른 엔티티 참조 등등 그래서
(그래서, 중첩 수준이 6 인), I가 예를 만든 또 다른 및 내가 원하는 것을 보여주십시오 : https://github.com/gladorange/hibernate-lazy-loading
나는 사용자가 있습니다.
사용자는 @OneToMany
좋아하는 것의 컬렉션 오렌지, 사과, 포도 품종 및 복숭아. 각 포도 나무에는 포도의 모음이 @OneToMany
있습니다. 각 과일은 단 하나의 String 필드가있는 다른 엔티티입니다.
나는 각 유형의 30 가지 좋아하는 과일로 사용자를 만들고 있으며, 각 포도 나무에는 10 가지 포도가 있습니다. 그래서, 전적으로 DB - 30 * 4 과일, 100 * 30 포도 및 한 사용자에 421 개체를 보유하고 있습니다.
그리고 원하는 것 : 6 개 이상의 SQL 쿼리를 사용하여로드하려고합니다. 그리고 각 쿼리는 큰 결과 집합을 생성해서는 안됩니다 (큰 경우 결과 집합이 200 개가 넘음).
6 요청 :
나의 이상적인 솔루션은 다음이 될 것입니다. 첫 번째 요청은 결과 세트의 사용자와 크기에 대한 정보를 결과 세트의 사용자와 크기에 대한 사과에 대한 1
두 번째 요청 반환 정보가 세 번째 (30)
, 네 번째와 다섯 번째 요청이 동일한 반환입니다 반환 , 두 번째로 (결과 세트 크기 = 30) Grapevines, Oranges 및 Peaches에 사용됩니다.
여섯 번째 요청이 SQL 세계에서 매우 간단 ALL 포도
을 위해 포도를 반환하지만 나는 JPA (최대 절전 모드)와 같은 달성 할 수 없다.
사용이
나는 다음과 같은 방법을 시도했다. 이것은 끔찍한 일입니다. 결과 집합은 30 * 30 * 30 * 30이고 실행 시간은 10 초입니다. 요청 수 = 3. 포도없이 시험해 보았습니다. 포도로 결과 세트의 x10 크기를 얻을 수 있습니다.from User u join fetch u.oranges ...
처럼, 가입 가져 오기 :그냥 지연로드를 사용하십시오. 이 예에서 가장 좋은 결과입니다 (@ Fetch = 포도에 대해서는 SUBSELECT 임). 그러나이 경우 각 요소 컬렉션을 수동으로 반복해야합니다. 또한 subselect 가져 오기가 너무 전역 설정이므로 쿼리 수준에서 작동 할 수있는 무언가를 갖고 싶습니다. 이상적인 결과 집합과 시간. 6 쿼리 및 43 밀리 초.
엔티티 그래프로로드 중. 페치 조인 (fetch join)과 동일하지만 모든 포도에 grapevine을 요청합니다. 그러나 결과 시간은 더 좋지만 (6 초), 여전히 끔찍합니다. 요청 건수> 30.
별도의 쿼리에서 엔티티의 "수동"로드로 JPA를 속이려고했습니다. 개체를 수동으로 로딩 (I 연관된로드를 포함하여이 쿼리를 완벽하게 제어 할 첫 번째 쿼리 : 마찬가지로 : 그것은 각 수집을위한 두 개의 쿼리를 필요로하기 때문에
SELECT u FROM User where id=1; SELECT a FROM Apple where a.user_id=1;
이, 게으른 로딩이 조금 더 나쁘다 Hibernate에 의해 동일한 엔티티를 lazy-load하는 두 번째 질의 (최대 절전 모드에 의해 자동으로 실행 됨)
실행 시간은 52, 쿼리 수 = 10 (사용자의 경우 1, 포도의 경우 1, 각 과일 컬렉션)
실제로 "수동"solut 이온을 SUBSELECT fetch와 함께 사용하면 "간단한"페치 조인을 사용하여 하나의 쿼리 (예 : @OneToOne
엔티티)에서 필요한 엔티티를로드 할 수 있으므로 사용하겠습니다. 하지만 컬렉션을로드하기 위해 두 가지 쿼리를 수행해야한다는 점이 마음에 들지 않습니다.
제안 사항?
나는 수동으로 5 개의 쿼리를 작성한다 : 먼저 열거 형'@ OneToMany'를 사용하여 두 번째 쿼리와 결합한 다음 설명 된 요청 3-6 개 중 하나를 사용하여 Java 코드로 개체를 어셈블한다. 물론 너무 우아하지는 않지만,'@ OneToMany' 곱셈이나 게으른 로딩은 필요하지 않습니다. –
@RomanPuchkovskiy 예, 이해가됩니다. 그러나로드 및 편집 후에도 인스턴스를 저장할 수 있어야합니다. 그래서 작동 할 수도 있지만 때로는 저장 중에 "예외를 찾을 수 없습니다"와 같은 예외가 발생합니다 (이전 컬렉션에서 엔티티를 검색하려고하기 때문에). 그래서 저는 수동으로 객체를 생성하지 않기로 결정했습니다. 그러나 저는 귀하의 조언이 읽기 전용 작업에 적합해야한다고 생각합니다. – EvilOrange