본문 바로가기

IT/JPA

JPA EntityGraph에 대해 알아보자

이번 시간에는 JPA EntityGraph에 대해 간단히 알아보고자 합니다.

JPA 2.0까지는 엔터티 연결을 로드하기 위해 일반적으로  FetchType을 사용했습니다. LAZY 및  FetchType Lazy 또는 EAGER를 통해서 JPA 제공자에게 관련 연관을 추가로 로딩합니다. 
그러나 FetchType은 정적이며 런타임에 이 두 전략 사이를 전환할 수 없습니다.

JPA 엔터티 그래프의 주요 목표는 엔터티의 관련 연결 및 기본 필드를 로드할 때 런타임 성능을 개선하는 것입니다.

간단히 말해서 JPA는 하나의 선택 쿼리에서 모든 그래프를 로드한 다음 더 많은 SELECT 쿼리와의 연결 가져오기를 방지합니다. 이것은 응용 프로그램 성능을 향상시키기 위한 좋은 접근 방식입니다.

EntityGraph를 코드로 예를 들어서 개념을 잡아보실께요 (실제 동작 코드는 아니고 개념을 설명하기 위한 코드입니다.)

예) 스토리를 쓸 수 있는 작성자를 각각 엔티티로 만들고 1:N연관관계를 맺었습니다.()

// Writer.kt (Entity)

@Entity
class Writer(
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long,
      val name: String,
      @OneToMany(fetch = FetchType.LAZY)
    @JoinColumn(name = "writer_id")
      var storyList:MutableList<Story>
)
// Story.kt (Entity)

@Entity
class Story(
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long,

      val title: String,
      val content: String
)
@Repository
interface WriterRepository : JpaRepository<Writer, Long> {

    override fun findById(id: Long): Optional<Writer>

      @EntityGraph(attributePaths = ["story"])
      override fun findByIdWithStory(id: Long): Optional<Writer>
}

Story 엔티티의 FetchType이 Lazy로 되어 있기때문에 Writer엔티티에서 story객체를 사용하려고 할때 story객체수 만큼 Select쿼리가 나갑니다.

반면 findByIdWithStory같은 경우는 @EntityGraph 애노테이션이 걸려 있어서 Join 쿼리 한번만 나가게 됩니다.

findById 쿼리

select writer from writer where writer_id = ?

@EntityGraph 적용된 findByIdWithStory 쿼리

select * from writer left outer join story where writer_id=?

- EntityGraphType

  • FETCH불러오게 합니다.
  • 지정한 연관관계 엔티티는 Eager로딩으로 불러오고, 그외 연관관계 엔티티들은 자동적으로 LAZY 로딩으로
  • LOAD해당 연관관계 어노테이션에서 가지고 있는 FetchType Default 값으로 설정해서 불러옵니다.
  • 지정한 연관관계 엔티티는 Eager로딩을 통해 불러오며, 그외의 엔티티 데이터들은 직접 선언한 FetchType이나

 

정리

오늘은 EntityGraph에 대해 간단히 알아보았습니다. 개념을 잘 파악하시어 프로젝트에 적절하게 사용하시길 바랍니다.