엔티티 그래프
연관된 엔티티들을 한번에 조회해 오는 방법.
join fetch 그거임.
엔티티 그래프 이전에, 객체 그래프 라는 것이
객체간의 연결된 관계를 보여주는 그래프임.
이런 거.
엔티티도 마찬가지임.
엔티티그래프란 엔티티간의 연결된 관계를 보여주는 그래프.
join fetch라는 개념이, 이런 엔티티그래프임.
join fetch라는게 이런 엔티티 그래프를 다 끌고온다는 개념임.
그래서 옛날에 join fetch 배웠을 때 fetch한 건 select에다가 별칭으로 fetch한 것의 일부분만 가져오고 그런 게 안된다고 했던 거임.
그래서 여튼,
지금 사실 Spring Data JPA가 아니라 Jpa스타일로 그냥 쿼리로 했는데,
@Query("select m from Member m join fetch m.team")
List<Member> findMemberFetch();
여튼 이렇게 하면,
select
m1_0.member_id,
m1_0.age,
t1_0.team_id,
t1_0.name,
m1_0.username
from
member m1_0
join
team t1_0
on t1_0.team_id=m1_0.team_id
쿼리 나갈 때 select 안에 저 team의 모든 데이터까지 다 포함시켜버림.
말 그대로 엔티티 그래프, 그 그래프의 관계를 쫙 끌고오는거임.
그럼 @EntityGraph는 뭐냐면,
예상하겠다시피 애노테이션인데,
내부적으로 join fetch 하는 애노테이션임
@Override
@EntityGraph(attributePaths = {"team"})
List<Member> findAll();
사용방법은
@EntityGraph(attributePaths = {"가져올엔티티필드명"})
attributePaths 직역은 속성 경로인데, join fetch해서 가져올 속성을 team이라고 한 거임.
그러면 엔티티에서 저 team이라는 필드를 join fetch해서 가져옴.
select
m1_0.member_id,
m1_0.age,
t1_0.team_id,
t1_0.name,
m1_0.username
from
member m1_0
left join
team t1_0
on t1_0.team_id=m1_0.team_id
실제로 이렇게 나감.
메소드명으로 만드는 쿼리문, 에도 가능하다.
@EntityGraph(attributePaths = {"team"})
List<Member> findGraphByUsername(String name);
select
m1_0.member_id,
m1_0.age,
t1_0.team_id,
t1_0.name,
m1_0.username
from
member m1_0
left join
team t1_0
on t1_0.team_id=m1_0.team_id
where
m1_0.username=?
이렇게 나간다.
그냥 @Query에도 저 @EntityGraph를 쓰면 자동으로 join fetch가 붙는다.
@EntityGraph(attributePaths = {"team"})
@Query("select m from Member m")
List<Member> findEntityGraph();
select
m1_0.member_id,
m1_0.age,
t1_0.team_id,
t1_0.name,
m1_0.username
from
member m1_0
left join
team t1_0
on t1_0.team_id=m1_0.team_id
이렇게 된다.
join fetch 할 때 나가는 쿼리가 left join 일 때도 있고, 그냥 join일 때도 있는데,
아마
@Query("select m from Member m join fetch m.team")
List<Member> findMemberFetch();
이렇게 join fetch 직접 치는 건 내가 저기 치면서 그냥 join인지 left 조인인지 치는거니까 저기서는 그냥 join이 나가고,
select
m1_0.member_id,
m1_0.age,
t1_0.team_id,
t1_0.name,
m1_0.username
from
member m1_0
join
team t1_0
on t1_0.team_id=m1_0.team_id
@EntityGraph, 그러니까 이게 내부적으로 join fetch 하게끔 도와주는 건데 이거의 기본 동작이 left join 인가 보다.
@Override
@EntityGraph(attributePaths = {"team"})
List<Member> findAll();
select
m1_0.member_id,
m1_0.age,
t1_0.team_id,
t1_0.name,
m1_0.username
from
member m1_0
left join
team t1_0
on t1_0.team_id=m1_0.team_id
그러니까 jpql에 직접 join fetch 치는 건 내가 jpql에 join이라는 걸 치는 시점에서 left join인지 그냥 join인지 결정하는 건데,
아무래도 그냥 join은 두 테이블 다 데이터가 있어야만 가져올 수 있기 때문에 데이터를 빠뜨리지 않고 일단 다 가져와야 (그래야 컬렉션 등도 만들 수 있으니? 일대다 뿐 아니라 넓게 봐서) 되기 때문에 기본이 left join 인 듯 싶다.
다음은 잘 쓰지는 않는데, 네임드로 EntityGraph를 미리 정의해 놓는 것도 있다.
엔티티에다가,
@NamedEntityGraph(name = "Member.all", attributeNodes = @NamedAttributeNode("team"))
public class Member {
...
이렇게 미리 EntityGraph를 정의해 놓는다.
저렇게 attributeNodes 즉, 속성노드 등도 정의해 놓고(attributePaths랑 이름은 다른데 목적은 같네. 저게 attributePaths로 변환 되는 듯),
@EntityGraph("Member.all")
List<Member> findGraphByUsername(String name);
이렇게 정의한 이름을 지정해서 가져올 수 있는 듯 하다.
사용해 보면
select
m1_0.member_id,
m1_0.age,
t1_0.team_id,
t1_0.name,
m1_0.username
from
member m1_0
left join
team t1_0
on t1_0.team_id=m1_0.team_id
where
m1_0.username=?
이렇게 제대로 나간다.
사용하지는 않을 것 같다.
보통 그냥 join fetch 사용한다면 @EntityGraph로
@EntityGraph(attributePaths = {"team"})
List<Member> findByUsername(String name);
메소드명으로 쿼리 생성 + @EntityGraph 조합으로 사용 하다가,
fetch 여러개 해야되고 막 복잡해지면,
@Query("select m from Member m join fetch m.team")
List<Member> findMemberFetch();
이런 식으로 직접 쿼리를 짜서 만들 것이다.
간단한 건 메소드명으로 쿼리 생성 + @EntityGraph
복잡한 건 JPQL로 직접 join fetch
'스프링데이터 + JPA > 스프링 데이터 JPA' 카테고리의 다른 글
20. 확장기능. 사용자 정의 리포지토리 (0) | 2023.11.23 |
---|---|
19. JPA 힌트, Lock (0) | 2023.11.23 |
17. 벌크성 수정쿼리 (0) | 2023.11.23 |
16. 스프링 데이터 JPA 페이징, 정렬 (0) | 2023.11.21 |
15. 순수 JPA 페이징, 정렬 (0) | 2023.11.21 |