2021. 2. 10. 16:21ㆍ프로그래밍 언어/Spring Framework
[인프런 김영한] JPA - 프록시
해당 글은 인프런 김영한강사님의 영상을 보고 정리한 글입니다.
Spring Boot, Spring Data JPA를 사용해 실습하였습니다.
김영한 인프런 : www.inflearn.com/users/@yh
▣ 프록시
- em.find() : 데이터베이스를 통해서 실제 Entity 객체 조회
- em.getReference() : 데이터베이스 조회를 미루는 가짜(프록시) Entitty 조회
* 실제 클래스를 상속 받아서 만들어짐
- 실제 클래스와 겉 모양은 같음
- 사용하는 입장에서는 진짜 객체인지 프록시 객체인지 구분하지 않고 사용하면 됨 (이론상)
* 프록시 객체는 실제 객체의 참조(target)를 보관
- 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드를 호출
▣ find() vs getOne()
Member
@Entity
public class Member{
@Id
@GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
Team
@Entity
public class Team{
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "TEAM_ID")
List<Member> members = new ArrayList<>();
}
예제코드 - 실행
Member member = new Member();
member.setName("user1");
memberRepository.save(member);
Member member1 = memberRepository.findById(member.getId()).get();
System.out.println(findMember.getId());
System.out.println(findMember.getName());
// find() 메소드를 사용하면 reference를 호출하는 시점에 select 쿼리가 출력이 된다.
Member findMember = memberRepository.findById(member.getId()).get();
// --여기까지 실행하면 select 쿼리가 실행된다. --
System.out.println(findMember.getId());
System.out.println(findMember.getName());
// --여기까지 실행하면 select 쿼리가 실행된다. --
// EntityManager의 getReference = JpaRepositocy의 getOne과 동일하다.
Member findMember2 = memberRepository.getOne(member.getId());
// --여기까지 실행하면 select 쿼리가 실행이 안된다. --
// System.out.println(findMember.getId());
// System.out.println(findMember.getName());
// --여기까지 실행하면 select 쿼리가 실행된다. --
// select 쿼리
Hibernate:
select
member0_.member_id as member_i1_0_0_,
member0_.name as name2_0_0_,
member0_.team_id as team_id3_0_0_,
team1_.team_id as team_id1_1_1_,
team1_.name as name2_1_1_
from
member member0_
left outer join
team team1_
on member0_.team_id=team1_.team_id
where
member0_.member_id=?
| find 메소드를 사용하면 해당 순간 select 쿼리가 실행이 되는데
getOne을 사용하게 되면 해당 값이 실제로 사용되는 시점에 select 쿼리가 실행된다.
▣ getOne이 가지고온 Class는 뭘까?
System.out.println(findMember2.getClass());
// 출력
class com.spring.jpa.Member$HibernateProxy$HmOVyLMj
| Hibernate가 만든 가짜 Proxy.
▣ 프록시의 특징 **
* 프록시 객체는 처음 사용할 때 한번만 초기화
* 프록시 객체를 초기화 할 때, 프록시 객체가 실제 Entity로 바뀌는게 아닌, 프록시 객체를 통해서 실제 Entity에 접근
* 프록시 객체는 원본 Entity를 상속받으며 타입 체크시 주의해야함. (== 대신, instance of 사용하기)
* 영속성 컨텍스트에 찾는 Entity가 이미 있으면 getReference()를 호출해도 실제 Entity를 반환.
* 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때, 프록시를 초기화하면 문제 발생.
- 영속성 컨텍스트가 close(), clear() 되면 Exception 발생.
'프로그래밍 언어 > Spring Framework' 카테고리의 다른 글
[인프런 김영한] JPA - 영속성전이(CASCADE) (0) | 2021.02.11 |
---|---|
[인프런 김영한] JPA - 즉시로딩 / 지연로딩 (0) | 2021.02.11 |
[인프런 김영한] JPA - @MappedSuperclass (0) | 2021.02.09 |
[인프런 김영한] JPA - 상속관계 매핑 (0) | 2021.02.09 |
[SpringMvc] Spring Interceptor 설정하기 (HandlerInterceptor) (0) | 2021.02.08 |