객체가 데이터베이스에 저장되어 있으므로 연관된 객체를 마음껏 탐색하기는 어렵다. JPA는 이 문제를 해결하려고 프록시라는 기술을 사용한다. 프록시를 사용하면 연관된 객체를 처음부터 데이터베이스에서 조회하는 것이 아니라, 실제 사용하는 시점에 데이터베이스에서 조회할 수 있다.
Member member = em.find(Member.class, "member1");
Member member = em.getReference(Member.class, "member1");
em.find()
: 엔티티를 직접 조회하면 조회한 엔티티를 실제로 사용하든 사용하지 않든 데이터베이스를 조회한다.
em.getReference()
: 엔티티를 실제 사용하는 시점까지 데이터베이스 조회를 미루고 싶으면 사용한다. 실제 객체도 생성하지 않고, 데이터베이스 접근을 위임한 프록시 객체를 반환한다.
프록시 클래스는 실제 클래스를 상속 받아서 만들어지므로 실제 클래스와 모양이 같다. 프록시 객체는 실제 객체의 참조(target)를 보관한다.(실제 객체의 메소드를 호출한다.)
org.hibernate.Hibernate.initialize(entity);
: 프록시 강제로 초기화
PersistenceUnitUtil.isLoaded(Object entity)
: 프록시 인스턴스의 초기화 여부
프록시 객체는 실제 사용될 때까지 데이터 로딩을 미룬다. 만약 조회 대상이 영속성 컨텍스트에 이미 있으면 프록시 객체를 사용할 이유가 없다. 따라서 실제 객체를 사용한다.
@ManyToOne(fetch = FetchType.LAZY)
엔티티를 조회할 때 연관된 엔티티도 함께 조회한다.
@ManyToOne(fetch = FetchType.EAGER)
영한님
: 하지만 실무에서 절대 즉시 로딩을 사용하지 마라! fetch 또는 엔티티 그래프를 이용하자! 예상치 못한 쿼리를 볼 수 있다.
특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 영속 상태로 만들고 싶을때 사용한다.
JPA에서 엔티티를 저장할 때 연관된 모든 엔티티는 영속 상태여야 한다.
하나의 부모가 자식들을 관리할 때, 사용하는 것이 좋다.
(게시글 하나에 첨부파일 경로 등등)
@OneToMany(cascade = CascadeType.ALL)
:영속성 전이는 연관관계를 매핑하는 것과는 아무 관련이 없다. 단지 엔티티를 영속화 할 때 연관된 엔티티도 같이 영속화하는 편리함을 제공한다.
Parent 앤티티만 영속화하면 Child 엔티티도 데이터베이스에 입력된 것을 확인할 수 있다.
JPA는 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능을 제공한다. 부모 엔티티의 컬렉션에서 자식 엔티티의 참조만 제거하면 자식 엔티티가 자동으로 삭제된다.
CASCADE
+ orphanRemoval
을 통해서 자식의 생명주기를 관리할 수 있다.