경주장

프록시와 연관관계 관리 본문

JPA

프록시와 연관관계 관리

달리는치타 2022. 1. 4. 22:48

프록시

Member를 조회할 때 Team도 함께 조회해야 할까?

프록시 기초

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

프록시 특징

  • 실제 클래스를 상속 받아서 만들어짐 
  • 실제 클래스와 겉 모양이 같다.
  • 사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용하면 됨(이론상)

 

 

 

 

  • 프록시 객체는 실제 객체의 참조(target)를 보관
  • 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드 호출

 

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


즉시 로딩과 지연 로딩

지연 로딩 (Lazy loading)을 사용해서 프록시로 조회 하자

@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;
 ..
 }

-> Member를 조회할때 team을 조회할 필요가 없다!

 

FetchType.Lazy

  • Member를 로딩할때 team은 프록시로 로딩한다.
  • 실제 Team을 사용하는 (Team의 Method를 호출, 필드를 조회) 시점에 DB조회가 발생한다.
  • 쿼리가 두번 나간다.

 

FetchType.Eager

  • Member를 로딩할때 team도 실제 객체가 바로 로딩
  • Member와 Team테이블을 조인한 쿼리가 한번 나간다.

프록시와 즉시로딩 주의

  • 가급적 지연 로딩만 사용(특히 실무에서)
  • 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생
  • 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다.
  • @ManyToOne, @OneToOne은 기본이 즉시 로딩 -> LAZY로 설정
  • @OneToMany, @ManyToMany는 기본이 지연 로딩

FetchType.Lazy를 쳐발쳐발하자

 


영속성 전이: CASCADE

  • 특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들도 싶을 때
  • 예: 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장.

 

 

e.g. 부모를 영속성 컨텍스트에 넣을때 자식도 함께 넣기

@Entity
public class Parent{

	@Id @GeneratedValue
    @Column("parent_id")
    private Long id;

	@OneToMany(mappedBy("parent"), casecade = CasecadeType.PERSIST)
	private List<chile> children = new ArrayList<>();
    ...
}

@Entity
public class Child{

	@Id @GeneratedValue
    @Column("child_id")
    private Long id;

	@ManyToOne
    @JoinedColumn("parent_id")
	private Parent parent;   
    ...
 }

고아 객체(orphan)

고아 객체 제거: 부모 엔티티와 연관관계가 끊어진 자식 엔티티 를 자동으로 삭제

'JPA' 카테고리의 다른 글

JPQL - 기본 문법  (0) 2022.01.05
값 타입  (0) 2022.01.05
고급 매핑  (0) 2022.01.04
다양한 연관관계 매핑  (0) 2022.01.04
연관관계 매핑 기초  (0) 2022.01.04