======================================================================================================================================================================
결론 : 1.조인해서 한번의 Query 로 Load 하려면 @EntityGraph 를 사용하여야 한다.
2. @NamedEntityGraph 선언할때 @NamedAttributeNode 에 원쿼리로 가져올 항목을 명시한다.
3. Repository 메소드에 @EntityGraph 선언하여 value에 사용할 @NamedEntityGraph 명을 적고, type 은 = EntityGraph.EntityGraphType. LOAD , FETCH 선택 사용.
4. 조인해서 가져오는 항목외에 다른 객체필드에 LAZY ,EAGER 를 선언해서 적어준다.
자세한 내용은 아래 참조.
======================================================================================================================================================================
엔티티 필드에 사용하는 LAZY, EAGER 를 Repository(메소드) 마다 다르게 사용하기 위해서 @NamedEntityGraph , @EntityGraph 를 사용한다.
@NameEntityGraph [ name = 이름을 선언 , attributeNodes = 조인해서 가져올 항목들 선언 ]
@EntityGraph [ value = NameEntityGraph name 값 , type = FETCH,LOAD 선택 ]
- FETCH: entity graph에 명시한 attribute는 EAGER로 패치하고, 나머지 attribute는 LAZY로 패치
- LOAD: entity graph에 명시한 attribute는 EAGER로 패치하고, 나머지 attribute는 entity에 명시한 fetch type이나 디폴트 FetchType으로 패치 (e.g. @OneToMany는 LAZY, @ManyToOne은 EAGER 등이 디폴트이다.)
* 이슈가 생겨서 쿼리수정이 필요할때
FETCH 로 선언했었을때 : EAGER 로 변경하고 싶을때 attribute 에 추가, LAZY 로 변경하고싶을경우 attribute에서 제거.
LOAD 로 선언했었을때 : EAGER 로 변경하고 싶을때 attribute 에 추가, LAZY 로 변경하고싶을경우 Entity 속성을 수정.
(여기서 Entity를 수정하는건 다른 API에 영향이 가기 때문에, FETCH 로 선언을 해서 사용하는게 추후 쿼리 이슈가 발생 했을경우 수정이 자유롭지 않을까 싶다.)
참고 : attributePaths 는 value 를 사용안하고 바로 필드를 적을때 사용.(value를 사용하는게 명시적으로 좋을듯하다) , subgraphs ( 2개이상 엔티티 조인할때 필요 )
Organization.java
@NamedEntityGraph(name = "Organization.subOrgList", attributeNodes = {@NamedAttributeNode("subOrganizationList")},subgraphs = {@NamedSubgraph(name = "subOrg",attributeNodes = @NamedAttributeNode("subOrganizationList"))}) public class Organization extends AbstractEntity implements AggregateRoot { ................... ................... } |
OrganizationRepository.java
@RepositoryRestResource public interface OrganizationRepository extends JpaRepository<Organization, Long>, QuerydslPredicateExecutor<Organization> , QuerydslBinderCustomizer<QOrganization> {
@EntityGraph(value = "Organization.subOrgList",attributePaths = {"parent"},type = EntityGraph.EntityGraphType.LOAD) Optional<Organization> findFirstByOrganizationCode(String organizationCode);
@EntityGraph(value = "Organization.subOrgList",attributePaths = {"parent"},type = EntityGraph.EntityGraphType.LOAD) Page<Organization> findAll(Pageable pageable);
List<Organization> findAllBy(); .... } |
========================================================================================================================================================
LAZY , EAGER 차이
fetch= FetchType.LAZY:데이터를 가져다 쓰는 시점에 쿼리를 실행한다. ( 즉 projection 으로 사용하지 않는 필드를 조회하는 API 를 호출할땐 쿼리가 실행되지 않음 )
fetch= FetchType.EAGER:데이터를 가져옴 조인해서 가져온다.( 단 Page<Entity> findAll(Pageable pageable) 메소드에는 적용되지 않음. @EntityGraph 사용해줘야됨 )
public class Organization extends AbstractEntity implements AggregateRoot { ..................... .....................
@OneToMany(mappedBy="parent", fetch= FetchType.LAZY, cascade=CascadeType.ALL) @RestResource(exported=false) @JsonManagedReference public List<Organization> subOrganizationList; } |
ex) projection 으로 subOrganizationList
'Web개발 > JPA' 카테고리의 다른 글
Spring data rest is Null 이나 is Not null (0) | 2021.04.21 |
---|---|
Projection 사용법 & Projection 안에 Projection (0) | 2021.03.17 |
JPA 로 프로젝트 하면서 느낀점 (0) | 2021.03.15 |
JPA 다대다 관계 풀기(1) (0) | 2021.03.14 |
@Entity 선언시 pk 역할 (0) | 2020.06.30 |