======================================================================================================================================================================

 

결론 : 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

+ Recent posts