본문 바로가기
Spring Study/JPA 기본

[JPA] 프록시와 연관관계 관리

by 정재인 2023. 11. 1.

프록시(Proxy)란?

· '대리', '대신'이라는 뜻을 가지며, 프로토콜에 있어 대리 응답 등에서 사용하는 개념이다.

· 클라이언트와 서버 사이에 존재하며, 중계기로서 대리로 통신을 수행하는 것을 프록시라 하며,

  그 중계 기능을 하는 주체를 '프록시 서버'라고 한다.

 

프록시 특징

· em.getReference(): 데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회

· 실제 클래스를 상속 받아서 만들어 진다.

· 실제 클래스와 겉 모양이 같다.

· 사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용하면 된다. (이론상)

· 프록시 객체는 실제 객체의 참조(target)를 보관

· 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드 호출

 

프록시 객체의 초기화

Member member = em.getReference(Member.class, "id1");
member.getName();

영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해도 실제 엔티티 반환

 


 

즉시 로딩과 지연 로딩

 

지연 로딩 LAZY를 사용해 프록시 조회

@Entity
public class Member{
    
    @Id
    @GeneratedValue
    private Long id;
    
    @Column(name = "USERNAME")
    private String name;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    
    ...
}

· 지연 로딩 LAZY를 사용해 프록시로 조회한다.

· 즉, Member가 실행되고 Team은 실제 Team을 사용하는 시점에 초기화(DB 조회)

 

즉시 로딩 EAGER를 사용해서 함께 조회

@Entity
public class Member{
    
    @Id
    @GeneratedValue
    private Long id;
    
    @Column(name = "USERNAME")
    private String name;
    
    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    
    ...
}

· 즉시 로딩(EAGER)는 Member 조회 시 항상 Team도 조회된다.

· JPA 구현체는 가능하면 조인을 사용해서 SQL을 한번에 함께 조회한다.

 

 

정리

· 실무에서는 가급적 지연 로딩(LAZY)만 사용한다.

· 즉시 로딩(EAGER)을 적용하면 예상치 못한 SQL이 발생된다.

· 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다.

· @ManyToOne, @OneToOne은 기본 값이 즉시 로딩

· @OneToMany, @ManyToMany는 기본 값이 지연 로딩

 


 

영속성 전이: CASCADE

· 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을 때 사용한다.

   ex) 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장

 

영속성 전이: 저장

@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)

· 영속성 전이는 연관관계를 매핑하는 것과 아무 관련이 없다.

· 엔티티를 영속화 할 때 연관된 엔티티도 함께 영속화하는 편리함을 제공할 뿐이다.

 

CASCADE 종류

· ALL: 모두 적용
· PERSIST: 영속
· REMOVE: 삭제
· MERGE: 병합
· REFRESH: REFRESH
· DETACH: DETACH

 


고아 객체

부모 엔티티와 연관관계가 끊어진 자식 엔티티를 의미한다.

 

특징

· 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동 삭제한다.

· 참조하는 곳이 하나일 때 사용해야 한다.

· 특정 엔티티가 개인 소요할 때 사용한다.

· @OneToOne, @OneToMany만 사용 가능

 

영속성 전이 + 고아 객체, 생명주기

· CascadeType.ALL + orphanRemoval = true

· 스스로 생명주기를 관리하는 엔티티는 em.persist()로 영속화, em.remove()로 제거

· 두 옵션을 모두 활성화 하면 부모 엔티티를 통해서 자식의 생명주기를 관리할 수 있다.

'Spring Study > JPA 기본' 카테고리의 다른 글

[JPA] 객체지향 쿼리 언어(JPQL)  (0) 2023.11.07
[JPA] 값 타입  (0) 2023.11.06
[JPA] 고급 매핑  (0) 2023.10.31
[JPA] 다양한 연관관계 매핑  (0) 2023.10.30
[JPA] 연관관계 매핑  (0) 2023.10.18

댓글