프록시(Proxy)
em.find() 는 DB를 통해 실제 엔티티 객체를 조회하지만,
em.getReference() 는 DB 조회를 미룰 수 있도록 프록시 엔티티 객체를 조회합니다.
(getReference 메서드를 호출하는 시점에는 DB 쿼리를 하지 않고 프록시 객체를 반환한 뒤, 사용되는 시점에 쿼리를 합니다)
프록시 객체는 실제 클래스를 상속받아서 생성되기에 실제 엔티티와 동일한 틀을 가졌습니다.
실제 객체의 참조(target)를 보관하고,
프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드를 호출합니다.
프록시 객체는 처음 사용할 때 한 번만 초기화되며, 초기화 시 프록시 객체가 실제 엔티티로 변경되는 것이 아닙니다.
(프록시 객체를 통해 실제 엔티티에 접근합니다)
프록시 객체는 원본 엔티티를 상속 받기 때문에 타입 체크에 주의해야 합니다.
(동일성 문제 발생, == 대신 instance of 사용합니다)
목표 엔티티가 영속성 컨텍스트에 존재하면 getReference()를 호출해도 실제 엔티티를 반환합니다.
반대로 영속성 컨텍스트에 목표 엔티티가 존재하지 않으면, 이후 find 호출시 프록시 객체를 반환하도록 하여 JPA에서 class 를 동일하게 맞춰줍니다)
만약, 엔티티가 준영속상태에 있으면, 프록시 초기화 시 문제가 발생하므로 주의가 필요합니다.
즉시 로딩(Eager Loading)과 지연 로딩(Lazy Loading)
연관관계에 있는 엔티티의 fetch type을 LazyLoading으로 설정하면,
대상 엔티티를 조회할 때, 연관관계에 있는 엔티티를 프록시 엔티티로 반환합니다.
지연로딩을 통해 불필요한 조회를 예방합니다.
반대로 즉시로딩을 사용하면, 대상 엔티티 조회 시점에 연관관계에 있는 엔티티 또한 조회합니다.
즉시 로딩은 JPQL에서 N+1 문제를 일으키는 등 예상하지 못한 SQL이 발생할 수 있습니다.
(@ManyToOne, @OneToOne의 기본값은 즉시로딩이므로 지연로딩으로 설정하는 것이 필요합니다)
(지연로딩을 사용한뒤, fetch join이나 @EntityGraph 기능을 통해 N+1 문제를 해결)
영속성 전이(CASCADE)
영속성 전이(CASCADE)는 특정 엔티티를 영속 상태로 만들면서,
연관된 엔티티도 함께 영속 상태로 만들고 싶을 때 사용합니다.
(부모 엔티티를 저장할 때, 자식 엔티티도 함께 저장하기 위해 사용합니다)
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
private List<Child> childList = new ArrayList<>();
ALL은 모두 적용하는 옵션이고, PERSIST는 영속성에 적용하는 옵션입니다.
REMOVE는 삭제에 적용합니다.
(추가로 MERGE, REFRESH, DETACH가 있습니다)
만약 자식 엔티티의 소유자가 하나라면 사용해도 되지만,
다른 곳에서도 소유하고 있다면 CASCADE사용에 어려움이 있습니다.
고아 객체
고아 객체는 부모 엔티티와 연관관계가 끊어진 자식 엔티티입니다.
orphanRemoval = true 를 사용하여 고아객체를 자동으로 제거할 수 있습니다.
CASCADE와 마찬가지로 자식 엔티티를 소유하는 엔티티가 하나일 때만 사용하는 것이 권장됩니다.
CascadeType.REMOVE처럼 동작합니다.
영속성 전이(CASCADE) + 고아 객체, 생명주기
CascadeType.ALL + orphanRemovel = true
스스로 엔티티의 생명주기를 관리할 때 em.persist()로 영속화하고, em.remove()로 제거합니다.
두 옵션을 모두 활성화하면 부모 엔티티를 통해 자식 엔티티의 생명주기를 관리할 수도 있습니다.
도메인 주도 설계(DDD)의 Aggregate Root 개념을 구현할 때 유용합니다.
'Java' 카테고리의 다른 글
[JPA(Jakarta Persistence API)] 다양한 쿼리 방법과 예시 (0) | 2024.03.14 |
---|---|
[JPA(Jakarta Persistence API)] 값 타입 (0) | 2024.03.13 |
[JPA(Jakarta Persistence API)] 상속관계 매핑, @MappedSuperclass (0) | 2024.03.12 |
[JPA(Jakarta Persistence API)] 연관관계 매핑 (0) | 2024.03.12 |
[JPA(Jakarta Persistence API)] 엔티티 매핑 (0) | 2024.03.12 |