책 [자바 ORM 표준 JPA 프로그래밍]을 참고하여 작성하였습니다.
8장 프록시와 연관관계 관리
즉시 로딩과 지연 로딩
- 즉시 로딩: 엔티티를 조회할 때 연관된 엔티티도 함께 조회
- @ManyToOne(fetch = FetchType.EAGER)
- 지연 로딩: 연관된 엔티티를 실제 사용할 때 조회
- @ManyToOne(fetch = FetchType.LAZY)
- 프록시 객체 : 지연로딩을 사용할 때 실제 엔티티객체 대신에 db 조회를 지연할 수 있는 가짜 객체
즉시 로딩
Member 엔티티
@Entity
public class Member{
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "TEAM_ID")
private Team team
}
즉시 로딩 실행 코드
Member member = em.find(Member.class, "member1");
Team team = member.getTeam();
sql로는 meber와 team을 조인해서 조회하게 된다.
지연 로딩
Member member = em.getReference(Meber.class, "member1");
- 프록시 클래스는 실제 클래스를 상속받아 만들어짐 -? 실제 클래스와 겉 모양이 같다
- 프록시 객체는 실제 객체에 대한 참조(targer)를 보관한다.
- 프록시 객체의 메소드를 호출하면(member.getName()처럼) 프록시 객체는 실제 객체의 메소드를 호출한다.
- 프록시 객체의 초기화 : 프록시 객체가 실제 사용될 때 db를 조회해 실제 엔티티 객체를 생성
- 프록시 객체에 member.getName()을 호출해 실제 데이터를 조회하려함
- 프록시 객체는 실제 엔티티가 생성되어 있지 않으면 영속성 컨텍스트에 실제 엔티티 생성을 요청(이것이 프록시 객체의 초기화)
- 3.영속성 컨텍스트는 db를 조회해서 실제 엔티티 객체 생성
- 프록시 객체는 생성된 실제 엔티티 객체의 참조를 Member target 멤버 변수에 보관
- 프록시 객체는 실제 엔티티 객체의 getName()을 호출해서 결과를 반환
- 엔티티를 프록시로 조회할 때 식별자 값을 파라미터로 전달. 프록시 객체는 이 식별자 값을 보관한다. -> 식별자 값을 조회하는 member.getId()를 호출해도 프록시는 초기화하지 않는다.(단, @Access(AccessType.FIELD))로 설정해야)
영속성 전이 : CASCADE
- CascadeType
- ALL
- PERSIST : 영속
- MERGE : 병합
- REMOVE : 삭제
- REFRESH : refresh
- DETACH : detach
영속성 전이 : 저장
@Entity
public class Parent{
@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
private List<Child> children = new ArrayList<Child>();
private static void saveWithCascade(EntityManager em){
Child child1 = new Child();
Child child2 = new Child();
Parent parent = new Parent();
child1.setParent(parent);
child2.setParent(parent);
parent.getChildren().add(child1);
parent.getChildren().add(child2);
em.persist(parent);
}
고아 객체
- JPA는 부모엔티티와 연관관계가 끊어진 자식 엔티티(고아 객체)를 자동으로 삭제하는 기능을 제공
orphanRemoval = true를 설정하면 고아 객체를 자동으로 삭제할 수 있다.