JPA 프록시, 지연 로딩, CASCADE, 고아 객체

김혁준·2024년 6월 28일

JPA

목록 보기
8/16

프록시 등장 배경

멤버와 팀이 연관관계일때 멤버를 조회하면 팀도 같이 조회해야 할까?
-> 팀을 조회할 일이 없으면 멤버만 조회해야 한다. 프록시가 해결해줌

프록시 기초

em.find() : 데이터베이슬르 통해 실제 엔티티 객체 조회
em.getReference() : 데이터베이스 조회를 미루는 프록시 엔티티 객체 조회

프록시의 특징

실제 클래스를 상속받아서 만들어졌다
실제 클래스와 겉 모양이 같다
프록시 객체는 실제 객체의 참조를 보관한다. 프록시 객체를 호출하면 실제 객체의 메소드를 호출한다.

프록시 객체의 초기화 과정

프록시 객체 호출 > 영속성 컨텍스트에 초기화 요청 > DB에 조회 > 실제 엔티티 생성 > 실제 엔티티의 메소드 호출 후 값 반환

프록시 객체의 특징

프록시 객체는 처음 사용할 때 한번만 초기화
프록시 객체가 초기화 할때 실제 엔티티로 바뀌는게 아니고 프록시 객체를 통해 실제 엔티티에 접근
프록시 객체는 원본 엔티티를 상속받았기 때문에 타입 체크시 주의해야 한다.( == 비교 실패하므로 instance of 사용)
영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티 반환
준영속 상태일때 프록시를 초기화하면 문제 발생

즉시 로딩과 지연 로딩

@ManyToOne, @OneToOne, @OneToMany에 fetch = FetchType.LAZY or fetch = FetchType.EAGER 사용

즉시 로딩 : 연관된 다른 엔티티도 쿼리
지연 로딩 : 연관된 다른 엔티티는 프록시로 처리되었다가 실제 호출시 쿼리

프록시와 즉시로딩 주의점

지연 로딩만 사용하자. 즉시 로딩 말고 JPQL fetch 조인이나 엔티티 그래프 기능을 사용하자
즉시 로딩을 적용하면 예상치 못한 SQL이 발생한다.
즉시 로딩은 JPQL에서 N+1 문제를 일으킨다
@ManyToOne, @OneToOne은 기본 즉시로딩이므로 LAZY로 설정하자

영속성 전이 CASCADE

특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을때 사용한다
예) 부모 엔티티를 저장할 때 자식 엔티티도 저장
@OneToMany(mappedBy="parent", cascade=CascadeType.ALL)

고아 객체

부모 엔티티와 연관관게가 끊어진 자식 엔티티를 자동으로 삭제
orphanRemoval = true 설정
부모의 컬렉션에서 자식 엔티티를 제거하면 자동으로 삭제 쿼리가 나가는 것이다.
참조하는 곳이 하나일 때 사용해야한다. 안그러면 사이드이펙트가 생김. 특정 엔티티가 개인 소유할 때 사용해야 한다. 예) 게시글과 댓글의 관계
참고로 고아 객체 설정시 부모를 제거한다면 자식도 함께 제거된다.

영속성 전이 + 고아 객체

CascadeType.ALL + orphanRemoval = true

두 옵션을 모두 활성화 하면 부모 엔티티를 통해 자식의 생명 주기를 관리할 수 있다.
CascadeType.ALL 을 통해 영속성 컨텍스트 들어갔다 나오는 주기가 부모와 같아지고
orphanRemoval = true을 통해 부모 객체에서 자식의 생명 주기를 DB와 쿼리를 날리면서 관리할 수 있다.

실전

모든 연관관계를 지연 로딩으로 바꾸자. @ManyToOne, @OneToOne을 전부 지연 로딩으로 변경
설계상 참조하는 부모가 하나인 자식엔티티를 부모 객체와 같은 생명주기를 갖고 싶을때 영속성 전이 ALL 설정

출처 : 인프런 자바 ORM 표준 JPA 프로그래밍 - 기본편

https://www.inflearn.com/course/ORM-JPA-Basic/dashboard

0개의 댓글