[SPRING] FetchMode 조인은 Spring JPA 저장소의 ManyToMany 관계에 아무런 차이가 없습니다.
SPRINGFetchMode 조인은 Spring JPA 저장소의 ManyToMany 관계에 아무런 차이가 없습니다.
나는 이것을하려고 노력하고있다 :
//...
class Person {
@ManyToMany(fetch = FetchType.EAGER)
@Fetch(FetchMode.JOIN)
private Set<Group> groups;
//...
}
personRepository.findAll ();을 수행 할 때 n + 1 개의 쿼리를 생성합니다. Spring JPA 저장소를 통해 마치 @Fetch 세트가없는 것처럼 말입니다. (먼저 모든 사람을 얻으려면 하나의 쿼리를, 그 다음 그룹을 가져 오려면 한 사람당 하나의 쿼리).
그래도 @Fetch (FetchMode.SUBSELECT)를 사용하면 효과가 있습니다! 2 개의 쿼리 만 생성합니다. (모든 사람에게 한 번, 그리고 그룹에 한 번). 따라서 최대 절전 모드는 JOIN이 아닌 일부 가져 오기 매개 변수에 반응합니다.
나는 또한 운이없는 EAGER 페칭 제거를 시도했다.
//...
class Person {
@ManyToMany()
@Fetch(FetchMode.JOIN)
private Set<Group> groups;
//...
}
나는 Spring JPA를 사용하고 있는데 이것은 나의 저장소를위한 코드이다 :
public interface PersonRepository extends JpaRepository<Person, Long> {
}
JOIN은 Spring JPA를 통해서만 작동하지 않습니까? 아니면 제가 잘못한 것을하고 있습니까?
해결법
-
==============================
1.많은 포럼과 블로그를 통해 문제를 읽을 수 있습니다. (내가 여기에 게시하기 전에 그렇게했을 수도 있습니다.) 나도 그렇게 생각합니다.
많은 포럼과 블로그를 통해 문제를 읽을 수 있습니다. (내가 여기에 게시하기 전에 그렇게했을 수도 있습니다.) 나도 그렇게 생각합니다.
참고 문헌 최대 절전 모드 포럼 춘계 포럼 비슷한 질문 1
-
==============================
2.JPA를 사용할 때 @Fetch (FetchMode.JOIN)을 사용할 수 없었습니다 (최대 절전 기준 API를 사용할 때 제대로 작동하지만). 이유를 설명하는 예제도 찾을 수 없었지만 몇 가지 해결 방법을 생각할 수 있습니다. .
JPA를 사용할 때 @Fetch (FetchMode.JOIN)을 사용할 수 없었습니다 (최대 절전 기준 API를 사용할 때 제대로 작동하지만). 이유를 설명하는 예제도 찾을 수 없었지만 몇 가지 해결 방법을 생각할 수 있습니다. .
그룹을 열심히로드하는 가장 간단한 방법은 JPQL을 사용하는 것입니다.
public interface PersonRepository extends JpaRepository<Person, String>{ @Query(value = "select distinct p from Person p left join fetch p.groups") List<Person> getAllPersons(); }
spring-data-jpa를 사용함에 따라, Specification을 사용하여 Group을 열심히로드 할 수도 있습니다. (1.4.x에서는 null을 리턴하는 스펙을 연결할 수 있습니다).
final Specification<Person> fetchGroups = new Specification<Person>() { @Override public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> query, CriteriaBuilder cb) { root.fetch("groups", JoinType.LEFT); query.distinct(true); return null; } };
이들 중 어느 것도 옵션이 아니라면 @Fetch (FetchMode.SUBSELECT)를 사용하는 것이 가장 좋습니다.
또 다른 옵션은 @BatchSize와 함께 @Fetch (FetchMode.SELECT)를 사용하는 것입니다. @BatchSize는 n + 1 쿼리의 문제를 해결하는 데 도움이됩니다. 배치 크기를 조정하면 CEIL (n / batch_size) +1로 실행되는 쿼리의 양을 줄일 수 있습니다.
@Entity @Table(name = "persons") public class Person { @Id String name; @ManyToMany(fetch = FetchType.EAGER) @BatchSize(size = 20) Set<Group> groups = new HashSet<>(); } @Entity @Table(name = "groups") public class Group { @Id String name; @ManyToMany(mappedBy = "groups", fetch = FetchType.LAZY) Set<Person> persons = new HashSet<>(); } public interface PersonRepository extends JpaRepository<Person, String>{}
personRepository.findAll ()을 실행할 때이 매핑 결과는 다음과 같습니다. 10 명을 포함하고 @BatchSize가 5로 설정된 데이터베이스에서.
Hibernate: select person0_.name as name1_ from persons person0_ Hibernate: select groups0_.persons_name as persons1_1_1_, groups0_.groups_name as groups2_1_, group1_.name as name0_0_ from persons_groups groups0_ inner join groups group1_ on groups0_.groups_name=group1_.name where groups0_.persons_name in ( ?, ?, ?, ?, ? ) Hibernate: select groups0_.persons_name as persons1_1_1_, groups0_.groups_name as groups2_1_, group1_.name as name0_0_ from persons_groups groups0_ inner join groups group1_ on groups0_.groups_name=group1_.name where groups0_.persons_name in ( ?, ?, ?, ?, ? )
@BatchSize는 FetchType.LAZY로 매핑 된 콜렉션에서도 작동합니다.
from https://stackoverflow.com/questions/18891789/fetchmode-join-makes-no-difference-for-manytomany-relations-in-spring-jpa-reposi by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] ServletContext 리소스 [/WEB-INF/applicationContext.xml]을 열 수 없습니다. (0) | 2018.12.24 |
---|---|
[SPRING] 스프링 MVC 사용자 정의 범위 Bean (0) | 2018.12.24 |
[SPRING] 스프링 보안 3.1에서 역할에 따라 목표 URL 결정 (0) | 2018.12.24 |
[SPRING] Java 런타임에서 낙타 경로 추가 (0) | 2018.12.24 |
[SPRING] "파일 이름"부분에 여러 점이있는 REST-ful URL 만들기 - Spring 3.0 MVC (0) | 2018.12.24 |