본문 바로가기
개발/Spring

JPA 프록시 개념/존재이유와 find(), getReferenceById()

by meanjung 2023. 8. 8.

프로젝트를 하면서 연관관계가 있는 데이터를 삽입해야 할 때 getReferenceById를 쓴다.

DB에는 bookmark(bm_id, u_id, r_id)로 되어있는데, 스프링에서는 객체 타입이기 때문에 데이터를 삽입할 때 다음과 같이 했다.

@Entity
@Table(name = "bookmark")
@Getter
public class ReviewBookmark {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "bm_id")
    private Long bookmarkId;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "u_id")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "r_id")
    private Review review;

    public ReviewBookmark() {

    }

    public ReviewBookmark(User user, Review review) {
        this.user = user;
        this.review = review;
    }

}
User user = userRepository.getReferenceById(userId);
Review review = reviewRepository.getReferenceById(reviewId);
ReviewBookmark bookmark = new ReviewBookmark(user, review);
reviewBookmarkRepository.save(bookmark);

 

getReferenceById

  • [지연로딩] 엔티티를 실제로 사용할 때까지 데이터베이스 조회를 지연시킨다.
  • 처음에는 프록시 객체로 갖고 있다가, 실제 엔티티 객체가 필요한 시점에서는 프록시 객체가 아닌 실제 엔티티를 반환한다.

findById

  • 데이터베이스로 조회문을 날려서 가져온다.

프록시 특징

  • 실제 클래스를 상속받아서 만들어진다.
  • 프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드를 호출한다.
    • 프록시 객체는 실제 객체의 참조를 보관한다.
  • 최초 프록시 객체의 target은 null 값을 갖고 있으나, 필요한 값을 가져올 때 초기화된다.
    • 프록시 객체는 처음 사용할 때 한 번만 초기화된다.
    • 프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는 것은 아니다. 초기화되면 프록시 객체를 통해 실제 엔티티에 접근 가능한 것이다.
  • 프록시 객체는 원본 엔티티를 상속받는다. 따라서 타입 체크 시 주의해야 한다. (== 비교 안 됨. instanceof 사용해야 함)
  • 영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference를 호출해서 실제 엔티티를 반환한다.
  • 영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때, 프록시를 초기화하면 문제가 발생한다.
Member m = em.getReference(Member.class, 1);

em.detach(m); // 영속성 컨텍스트가 관리 안 함. 준영속 상태

m.getUsername(); // Lazy Initialization Exception

 

 

JPA에서 프록시 패턴이 왜 사용됐을까?

JPA에서 엔티티를 조회할 때 LAZY 로딩/ EAGER 로딩이 있다. 

이 개념을 JPA는 내부적으로 프록시를 사용하여 구현했다. 

 

 


https://velog.io/@jin0849/JPA-%ED%94%84%EB%A1%9D%EC%8B%9CProxy

 

[JPA] 프록시(Proxy)

JPA에서 객체를 조회하는 두가지 메소드가 있다.(두 메소드 전부 EntityManager에 정의된 메소드이다.)데이터베이스를 통해서 실제 엔티티 객체 조회데이터베이스 조회를 미루는 가짜 엔티티(프록시

velog.io

 

댓글