김영한 님의 "자바 ORM 표준 JPA 프로그래밍" 책을 정리한 포스팅 입니다.
1. 프록시
- 엔티티를 조회할 때, 연관된 엔티티를 항상 사용하는 것은 아닙니다.
- 모든 연관관계를 한꺼번에 가져오게 될 경우, 성능이 떨어질 수 있습니다.
지연 로딩
- 엔티티가 실제 사용될 때, 데이터베이스 조회를 하는 방법입니다.
프록시 객체
- 실제 엔티티 객체 대신에 가짜 엔티티 객체를 사용합니다. (DB 접근 위임)
- 실제 클래스를 상속받아 만들어짐 (겉모양 같음)
- 실제 객체의 참조를 보관하며, 프록시 객체의 메소드를 호출하면 실제 객체의 메소드를 호출 (데이터베이스 조회 지연 목적)
em.getReference()
Member member = em.getReference(Member.class, "id1");
member.getName();
- 프록시 객체 반환 + 엔티티 객체 생성 X (DB 조회 X)
- (엔티티가 영속성 컨텍스트에 존재 시) 실제 엔티티 반환
초기화 과정
class MemberProxy extends Member {
Member target = null;
public String getName() {
if (target == null) {
// 2. 초기화 요청
// 3. DB 조회
// 4. 실제 엔티티 생성 및 참조 보관
this.target = ...;
}
return target.getName();
}
}
- 프록시 객체에 member.getName()을 호출하여 실제 데이터를 조회합니다.
- 프록시 객체는 실제 엔티티가 생성되어 있지 않으면, 영속성 컨텍스트에 실제 엔티티 생성을 요청합니다.
- 영속성 컨텍스트는 데이터베이스를 조회해서 실제 엔티티 객체를 생성합니다.
- 프록시 객체는 생성된 실제 엔티티 객체의 참조를 멤버변수에 저장합니다.
특징
- 처음 사용할 때 한번만 초기화됩니다.
- 영속성 컨텍스트에 의해 초기화가 수행됩니다.
- 초기화 작업을 통해 실제 객체에 접근이 가능해집니다.
LazyInitializationException
- 준영속 상태에서 초기화 요청 시
프록시와 식별자
Member member = em.getRefreence(Member.class, "id1");
member.getName();
- 식별자 값 보관 (파라미터로 식별자 값 전달됨)
- 식별자 값 접근 가능 (프록시 초기화 X)
- 유용) 엔티티 참조만 필요할 경우 (상세 데이터 필요 X)
프록시 확인
PersistenceUnitUtil().isLoaded()
boolean isLoad = em.getEntityManagerFactory().getPersistenceUnitUtil().isLad(entity);
- 프록시 인스턴스의 초기화 여부 확인
2. 즉시 로딩과 지연 로딩
즉시 로딩 (FetchType.EAGER)
- 엔티티를 조회할 때 연관된 엔티티도 함께 조회합니다.
NULL 제약조건과 조인 전략
- 기본적으로 즉시 로딩 시, 외부 조인을 사용합니다. (외래키 속성이 nullable 일 수 있음)
- 외래키에 NOT NULL 설정을 할 경우, 내부 조인으로 쿼리를 작성합니다. (@JoinColumn(nullable=false))
지연 로딩 (FetchType.LAZY)
- 연관된 엔티티를 프록시로 조회합니다.
- 실제 데이터가 필요한 순간이 되어서야 데이터베이스 조회 (프록시 객체 초기화 O)
3. 지연 로딩 활용
컬렉션에 FetchType.EAGER 사용 시 주의점
컬렉션을 두 개 이상 즉시 로딩 X
- 성능 저하
컬렉션 즉시 로딩 항상 외부 조인 O
- 외래키가 null일 경우 아무런 결과 안나올 수 있음
4. 영속성 전이 : CASCADE
- 특정 엔티티를 영속 상태로 만들 때, 연관된 엔티티도 함께 영속 상태로 만들 경우 사용합니다. (외래키 제약조건 기반)
- 엔티티를 저장할 때, 연관된 모든 엔티티는 영속 상태여야 합니다.
- 엔티티를 영속화할 때, 연관된 엔티티도 같이 영속화하는 편리함을 제공합니다.
- CASCADE 옵션을 사용합니다.
저장
CascadeType.PERSIST
@Entity
public class Parent {
...
@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
private List<Child> children = new ArrayList<Child>();
}
- 부모를 영속화할 때, 연관된 자식들도 함께 영속화합니다.
삭제
CascadeType.REMOVE
@OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE)
- 부모와 자식 엔티티 모두 제거하는 쿼리를 생성합니다.
고아 객체
@Entity
public class Parent {
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy = "parent", orphanRemoval = true)
private List<Child> children = new ArrayList<Child>();
...
}
- 부모 엔티티와 연관관계가 끊긴 자식 엔티티를 자동으로 삭제할 수 있습니다.
- @OneToMany에서만 사용할 수 있습니다.
'Spring > Spring Data JPA' 카테고리의 다른 글
[Spring Data JPA] 3-8. Repository query return types (0) | 2024.08.02 |
---|---|
[Spring Data JPA] 3-7. Repository query keywords (0) | 2024.08.02 |
[자바 ORM 표준 JPA 프로그래밍] 7. 고급 매핑 (1) | 2023.12.28 |
[자바 ORM 표준 JPA 프로그래밍] 6. 다양한 연관관계 매핑 (0) | 2023.12.27 |
[자바 ORM 표준 JPA 프로그래밍] 5. 연관관계 매핑 기초 (0) | 2023.12.27 |