jpa 에서는 em.find() 는 데이터베이스를 통해서 실제 엔티티 객체를 조회하는 메서드이고
em.getReference()는 DB의 조회를 미루는 가짜(프록시) 엔티티 객체를 조회하는 메서드이다.
em.find()
말고, em.getReference()
라는 메서드도 제공된다.em.find()
는 DB를 통해서 실제 엔티티 객체를 조회하는 메서드이고, em.getReference()
는 DB의 조회를 미루는 가짜(프록시) 엔티티 객체를 조회하는 메서드이다.@Entity
@Getter
@Setter
public class Member extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String username;
private Integer age;
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Lob
private String description;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
@OneToOne
@JoinColumn(name = "locker_id")
private Locker locker;
@OneToMany(mappedBy = "member")
private List<MemberProduct> memberProducts = new ArrayList<>();
}
Member member = em.getReference(Member.class, member.getId());
member.getName();
1.em.getReference()로 프록시 객체를 가져온 다음에, getName() 메서드를 호출 하면
2.MemberProxy 객체에 처음에 target 값이 존재하지 않는다. JPA가 영속성 컨텍스트에 초기화 요청을 한다.
3.영속성 컨텍스트가 DB에서 조회해서
4.실제 Entity를 생성해준다.
5.그리고 프록시 객체가 가지고 있는 target(실제 Member)의 getName()을 호출해서 결국 member.getName()을 호출한 결과를 받을 수 있다.
6.프록시 객체에 target이 할당되고 나면, 더이상 프록시 객체의 초기화 동작은 없어도 된다.
1.프록시 객체는 처음 사용할 때 한 번만 초기화 된다.
2.프록시 객체를 초기화 할 때, 프록시 객체가 실제로 엔티티로 바뀌는 것은 아니다. 초기화 되면 프록시 객체를 통해서 실제 엔티티에 접근 가능하다.
3.정확히 말하면 target에 값이 채워지는 것 뿐이다.
4.(심화)프록시 객체는 원본 엔티티를 상속 받는다고 했다. 프록시 객체와 원본 객체가 타입이 다르다. 타입 체크시 주의해야 한다.
== 비교 실패한다. jpa에서 타입 비교는 웬만하면, instanceOf를 사용해야 한다.