프록시
엔티티를 실제 사용하는 시점까지 데이터베이스 조회를 미루 싶으면 EntityManager.getReference() 메소드를 사용
- 프록시와 식별자
Team team = em.getReference(Team.class, “team1”); //식별자 보관
team.getId(); //초기화 되지 않음
엔티티 접근 방식을 필드(@Access(AccessType.FIELD))로 설정하면 프록시 객체를 초기화
- 프록시 확인
프록시 인스턴스의 초기화 여부를 확인
boolean isLoad = em.getEntityManagerFactory().getPersistenceUnitUtil().isLoaded(entity);
- 즉시 로딩과 지연 로딩
–즉시로딩 : 엔티티를 조회할 때 연관된 엔티티도 조회
em.find(Member.class, “member1”)를 호출할 때 회원 엔티티와 연관된 팀 엔티티도 함께 조회
@ManyToOne(fetch = FetchType.EAGER) 로 사용
–지연로딩 : 연관된 엔티티를 실제 사용할 때 조회
member.getTeam().getName()처럼 조회한 팀 엔티티를 실제 사용하는 시점에 JPA가 SQL을 호출
@ManyToOne(fetch = FetchType.LAZY)
JPA 기본 페치 전략
@ManyToOne, @OneToOne: 즉시 로딩(FetchType.EAGER)
- (optional = false) : 내부 조인
- (optional = true) : 외부 조인
@OneToMany, @ManyToMany: 지연 로딩(FetchType.LAZY)
- (optional = false): 외부 조인
- (optional = true): 외부 조인
연관된 엔티티가 하나면 즉시 로딩, 컬렉션이면 지연 로딩
모든 연관관계에 지연 로딩을 사용하고 APP개발이 완료 단계에 왔을 때 즉시 로딩을 최적화
영속성 전이 : CASCADE
부모와 자식 엔티티를 한 번에 영속화
@Entity
public class Parent {
…
@OneToMany(mappedBy = “parent”, cascade = CascadeType.PERSIST)
private List<Child> children = new ArrayList<Child>();
…
}
저장
private static void saveWidthCascade(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);
}
삭제
CascadeType.REMOVE
Parent findParent = em.find(Parent.class, 1L);
em.remove(findParent);
부모 엔티티만 삭제하면 연관된 자식 엔티티도 함께 삭제
고아 객체
부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하는 기능을 제공
@Entity
public class Parent {
@Id @GeneratedValue
private Long id;
@OneToMany(mappedBy = “parent”, orphanRemoval = true)
private List<Child> children = new ArrayList<Child>();
…
}
삭제한 엔티티를 다른 곳에서도 참조한다면 문제가 발생할 수 있으므로 @OneToOne, @OneToMany에만 사용할 수 있다.
출처 : 자바 ORM 표준 JPA 프로그래밍 김영한 지음