Member를 조회할 때 Team도 함께 조회해야 할까?
=> 비즈니스 로직에 따라 다르다. 항상 Team을 함께 조회할 필요는 없다.
em.find() vs em.getReference()
💡 프록시 객체의 초기화
Member member = em.getReference(Member.class, “id1”); member.getName(); // 프록시 초기화!!
- getName() 호출시 target이 비어있으면 영속성 컨텍스트에 초기화를 요청함
- 영속성 컨텍스트가 DB를 조회해 실제 엔티티 객체(Member)를 생성해 target에 진짜 객체를 연결해줌.
Member m1 = em.getReference(Member.class, member1.getId());
Member m2 = em.getReference(Member.class, member2.getId());
System.out.println("m1 == m2: " + (m1.getClass() == m2.getClass())); // false
System.out.println("m1 instanceof: " + (m1 instanceof Member)); // true
Member reference = em.getReference(Member.class, member1.getId());
System.out.println("reference: " + reference.getClass()); // Member 반환
Member refMember = em.getReference(Member.class, member1.getId());
Member findMember = em.find(Member.class, member1.getId());
Member refMember = em.getReference(Member.class, member1.getId());
em.detach(refMember); // 준영속 상태로 전환
refMember.getName();
PersistenceUnitUtil.isLoaded(Object entity)
entity.getClass().getName() 출력(..javasist.. or HibernateProxy...)
org.hibernate.Hibernate.initialize(entity);
member.getName()
지연 로딩을 사용해 프록시로 조회
-> Team 객체를 조회하는 시점에 쿼리가 나간다.
@Entity
public class Member {
private String name;
@ManyToOne(fetch = FetchType.LAZY) //**
@JoinColumn(name = "TEAM_ID")
private Team team;
}
Team 객체의 메소드 실행시 쿼리 발생
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member1 = new Member();
member1.setName("member1");
em.persist(member1);
em.flush();
em.clear();
Member m = em.find(Member.class, member1.getId());
m.getTeam().getName(); // 이 시점에 프록시 조회(지연로딩LAZY)
Member와 Team을 JOIN해 한 번에 가져옴.
@Entity
public class Member {
private String name;
@ManyToOne(fetch = FetchType.EAGER) //**
@JoinColumn(name = "TEAM_ID")
private Team team;
}
em.find() 할 때 Member와 Team을 다 가져옴.
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member1 = new Member();
member1.setName("member1");
em.persist(member1);
em.flush();
em.clear();
Member m = em.find(Member.class, member1.getId()); // 이 때 Member, Team 다 가져옴
m.getTeam().getName(); // 프록시가 아닌 진짜 호출
Member와 Team은 자주 함께 사용 -> 즉시 로딩
Member와 Order는 가끔 사용 - > 지연 로딩
Order와 Product는 자주 함께 사용 -> 즉시 로딩
특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만듦
ex) 부모 엔티티를 저장할 때 자식 엔티티도 함께 저장
@OneToMany(mappedBy="parent", cascade=CascadeType.PERSIST)
private List<Child> childList = new ArrayList<>();
고아 객체 제거 : 부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제
@OneToMany(mappedBy="parent", orphanRemoval = true)
private List<Child> childList = new ArrayList<>();
Parent parent1 = em.find(Parent.class, id);
parent1.getChildren().remove(0); // 자식 엔티티를 컬렉션에서 제거
=> DELETE FROM CHILD WHERE ID=?
@OneToMany(mappedBy="parent", cascade=CascadeType.PERSIST, orphanRemoval = true)
private List<Child> childList = new ArrayList<>();