[JPA] 프록시와 연관관계
em.find 메서드를 사용하면 데이터베이스를 통해 실제 엔티티 객체를 조회하고, em.getReference 메서드를 사용하면 데이터베이스 조회를 미루는 프록시 엔티티를 조회한다.
여기서 프록시는 실제 엔티티 클래스를 상속받아서 만들어지고, 실제 클래스와 겉으로 보기에는 차이가 없다.
프록시에는 클래스의 값인 id와 name은 없지만 클래스를 가리키는 target을 가진다.
getId() 또는 getName() 메서드가 프록시에 호출되면 target에 있는 getId()나 getName() 을 대신 호출하는 방식으로 동작한다.
getReference 메서드를 사용하면 member의 프록시를 가져온다.
그 후 getName() 메서드를 호출하는데, 아직 target은 초기화되지 않아 실제 Entity를 가리키지 않는 상태이다.
JPA는 영속성 컨텍스트에게 초기화를 요청하고 영속성 컨텍스트는 데이터베이스에서 실제 엔티티를 생성해 프록시의 target과 연결한다.
프록시에 값이 없는 경우 영속성 컨텍스트를 통해 초기화하는 로직을 기억하자.
프록시 객체는 처음 사용할 때 한 번만 초기화되고 초기화되면 프록시를 통해 실제 엔티티에 접근할 수 있게 된다.
getReference 메서드를 통해 얻은 객체가 무조건 프록시인건 아니다.
영속성 컨텍스트에 찾으려 하는 엔티티가 이미 존재하는 경우 프록시 대신 실제 엔티티를 반환한다.
비슷한 예시로 find 메서드를 통해 얻은 객체 또한 무조건 실제 객체는 아니다.
바로 직전에 getReference로 동일한 객체를 얻어왔다면 find 메서드를 통해 프록시를 반환하게 된다.
점점 복잡해지는데.. 간단하게 JPA에서는 특수한 경우 == 연산 결과를 true로 보장하는 방향으로 작동한다고 생각하면 된다.
그냥 이런 경우도 있구나 하고 넘어가자. 자주 만나게 되는 상황은 아니다.
getReference로 프록시를 얻어온 후 getName() 메서드를 호출하면 위의 그림처럼 영속성 컨텍스트를 통해 target을 초기화하게 되는데, 모종의 이유로 영속성 컨텍스트에 원하는 객체가 관리되고 있지 않는 경우면 어떻게 될까? (detach, close 등)
LazyInitializationException 에러가 발생해 target을 초기화하는데 실패한다.
위와 같이 데이터베이스가 설계된 상황에서 Member를 조회할 때 Team도 함께 조회해야 할까?
Member를 조회하고 Member 관련 정보만 사용하는 경우 Team을 조회할 필요가 없지만, Member를 조회하면서 Member가 속한 Team 관련 정보를 사용해야 하는 경우 Team을 조회해서 데이터베이스에서 정보를 받아와야 한다.
엔티티 클래스에서 Team을 정의할 때 @ManyToOne 애너테이션에 fetch 속성을 LAZY로 설정하면 지연 로딩으로 설정된다.
지연 로딩을 사용하면 find 메서드로 Member를 조회할 때 일단 Member만 조회해 두고 실제로 Team을 사용하는 시점에 Team을 데이터베이스에서 조회해서 사용하는 방식으로 작동한다.
fetch 속성을 EAGER로 설정하면 즉시 로딩으로 설정되고 Member를 조회할 때 항상 Team도 함께 조회하는 방식으로 동작한다.
실무에서는 지연 로딩만 사용하는 편이 합리적이다.
즉시 로딩을 적용하면 쿼리를 한 번에 보낼 수 있어 특정 상황에서 효율적으로 동작할 것 같지만, 예상치 못한 sql이 발생할 수 있다.
프로젝트의 규모가 큰 경우 즉시 로딩을 사용하면 한 번에 전달되는 쿼리가 굉장히 많아지고 이 부분이 문제를 일으킬 수 있다.
JPQL을 사용할 때도 발생하는데.. 자세한건 JPQL을 제대로 공부하면서 살펴보자.
@ManyToOne @OneToOne 애너테이션은 기본값이 즉시 로딩으로 설정돼있으니 fetch 속성값을 꼭 바꿔주자. (ToOne 시리즈)
'Spring > JPA' 카테고리의 다른 글
[JPA] 값 타입 (0) | 2022.12.26 |
---|---|
[JPA] 영속성의 전이와 고아 객체 (0) | 2022.12.24 |
[JPA] 상속관계 매핑 (0) | 2022.12.23 |
[JPA] 다양한 연관관계 매핑 (0) | 2022.12.22 |
[JPA] 연관관계 매핑 (0) | 2022.12.22 |
댓글
이 글 공유하기
다른 글
-
[JPA] 값 타입
[JPA] 값 타입
2022.12.26 -
[JPA] 영속성의 전이와 고아 객체
[JPA] 영속성의 전이와 고아 객체
2022.12.24 -
[JPA] 상속관계 매핑
[JPA] 상속관계 매핑
2022.12.23 -
[JPA] 다양한 연관관계 매핑
[JPA] 다양한 연관관계 매핑
2022.12.22