티스토리 뷰
# 이 게시글은 김영한님의 인프런-자바 ORM 표준 JPA 프로그래밍 강의를 많이 참고했습니다
# 프록시
DB 조회를 나중으로 미루는 가짜 객체.
* 실제 클래스를 상속받아서 생성. 겉 모양이 같다
-> 사용하는 입장에서는 얘가 진짜 객체인지 프록시 객체인지 모르고 사용해도 된다(이론상 그렇다)
* em.getReference() 메소드로 프록시 객체 조회가능 <-> em.find() = 실제 엔티티 객체
* 프록시 객체는 실제 객체의 참조를 보관. 프록시 객체를 호출하면 프록시 객체가 실제 객체의 메소드 호출.
* 프록시 객체는 처음 사용할 때 한번만 초기화한다
* 프록시 객체를 초기화 하는 것이 프록시 객체가 실제 객체로 바뀌는 것이 아니다.
(프록시 객체를 통해서 실제 엔티티에 접근이 가능해지는 것)
* 준영속 상태인 엔티티로 프록시를 초기화할 수 없다.
* 프록시 객체는 원본 엔티티를 상속받기 때문에 타입 체크시 유의 (instance of 사용)
* 영속성 컨텍스트에 찾는 엔티티가 있으면, em.getReference를 사용해도 실제 엔티티를 반환.
-> 동일 트랜잭션 내에서 **동일성 보장** (==비교시 true)
==
em.find() 이후에 em.getReference()를 하면 둘 다 실제 엔티티가 반환된다
em.getReference() 이후에 em.find()를 하면 의외로 둘 다 프록시 객체가 반환된다.
왜냐? => 동일성 보장을 하기 위해.
-> 따라서 em.find()를 했음에도 프록시 객체가 튀어나올 수 있다는 것을 인지하고, 프록시든 아니든 관계없이 사용할 수 있도록 설계하는 것이 중요하다.
-> 그렇기 때문에 instance of 를 사용하라는 것!!
==
1. 회원 엔티티를 em.find()로 조회한다
->영속성 컨텍스트에 팀 엔티티가 있는가?
(있다: 팀 엔티티 바로 사용 / 없다: 팀 프록시 객체 반환)
2. 팀 엔티티에 접근하려는 순간 DB에서 실제 팀 엔티티를 조회, 영속성 컨텍스트에 등록
3. 영속성 컨텍스트에 등록된 팀 엔티티를 팀 프록시 target에 연결. 프록시 초기화
4. 이후 클라이언트는 초기화된 팀 프록시를 거쳐서 팀 엔티티에 접근
==
# 지연 로딩(LAZY LOADING)
엔티티가 실제 사용될때까지 데이터베이스 조회를 지연하는 방법.
- "프록시 객체" 사용. 프록시를 살제 사용할 때 DB 쿼리를 날려서 초기화.
# 즉시 로딩(EAGER LOADING)
연관된 엔티티 전부를 조인을 통해서 즉시 조회.
- 연관된 엔티티가 많은 경우, 지연 로딩은 프록시 객체로 대체해 실제 접근 시점에 DB에서 조회할 수 있지만, 즉시 로딩의 경우 엔티티를 한꺼번에 싹 끌어와야 한다. 이때 전혀 예상치 못한 쿼리가 발생할 수 있음.
** 모든 연관관계는 지연 로딩을 사용해라 **
- 즉시로딩을 사용할 경우 N+1 문제를 야기할 수 있다.
- @ManyToOne, @OneToOne은 즉시 로딩이 기본값이므로 LAZY로 바꿔 사용할것!
[1+N 문제]
한번의 쿼리로 조회한 N개의 엔티티가 또 다른 N개의 조회 쿼리를 발생시키는 문제.
-> 엔티티가 즉시로딩일 경우, 조회 시에 모든 연관관계를 같이 가져오기 때문에 즉시 추가적인 쿼리를 발생시킨다.
-> 지연로딩이라면 프록시로 대체하기 때문에 쿼리 발생 시점을 뒤로 늦출 수 있다.
(발생하지 않는 것이 아니다. 프록시에 접근하는 순간까지 쿼리 발생을 늦출 뿐..)
-> 이를 완전하게 해결하려면 Fetch Join, EntityGraph 등을 사용해야 한다.
# 영속성 전이 (Transitive Persistence)
엔티티를 영속 상태로 만들 때 연관된 엔티티도 한꺼번에 영속 상태로 만들고 싶을때 사용.
(부모 엔티티를 저장할 때 자식 엔티티도 한꺼번에 저장하도록)
- 엔티티를 저장할 때, 연관된 모든 엔티티는 영속상태로 있어야한다.
-> 부모 엔티티만 영속상태로 만들면 연관된 자식 엔티티를 한꺼번에 영속상태로 만들어 같이 저장시킬 수 있다.
(em.persist(child1), em.persist(child2)... 굳이 안해도 된다는 뜻)
- 연관관계를 맺어놓고, cascade = CascadeType.[타입]로 설정해서 사용.
-> 영속성 전이와 연관관계 매핑은 관련이 없다. 단순 반복작업을 줄여주는 것 뿐
* CASCADE의 범위에 대해서..
- 자식 엔티티를 부모 엔티티가 완전히 개인 소유(단일 소유자)하는 경우에만 사용해라. (ex, 게시판과 첨부파일 관계)
(타 엔티티가 자식 엔티티를 참조하지 않는 경우에만 사용)
- 부모와 자식간 생명주기가 거의 같을 때 사용.
- 관계가 애매하면 그냥 사용하지 않는 것이 좋다..
# 고아 객체 (Orphan Removal)
부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제한다.
- 영속성 컨텍스트 플러시 시점에 자동 적용.
- 영속성 전이와 마찬가지로 단일 소유자 관계에서만 사용해야 한다. (@OneToOne, @OneToMany)
- 부모를 제거하면 자식도 한꺼번에 제거된다.
* 영속성 전이 + 고아객체 제거를 동시에 사용한다는 것은, 자식 엔티티의 생명주기를 부모 엔티티를 통해서 관리할 수 있다는 것이다
'웹 > Spring' 카테고리의 다른 글
SpringBoot | DataIntegrityViolationException 해결 (0) | 2022.04.05 |
---|---|
JPA에 대해 공부해보자 (6) - JPQL (0) | 2022.03.24 |
JPA에 대해 공부해보자 (4) - 상속관계 매핑 (0) | 2022.03.21 |
JPA에 대해 공부해보자 (3) - 연관관계 매핑 (0) | 2022.03.21 |
JPA에 대해 공부해보자 (3) - 매핑 (0) | 2022.03.19 |