프로젝트를 하면서 연관관계가 있는 데이터를 삽입해야 할 때 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
'개발 > Spring' 카테고리의 다른 글
MySQL 비관적 락을 이용한 인원 제한 구현하기 (0) | 2023.08.17 |
---|---|
[N+1 문제] 일반조인, fetch조인으로 OSIV, LAZY/EAGER, N+1문제 확실히 이해하기 (0) | 2023.08.16 |
[N+1 문제] 게시글 댓글 조회 기능 querydsl로 해결하기 (0) | 2023.08.06 |
N+1 문제란? feat. 해결방법 - 개념적 이야기 (0) | 2023.08.06 |
QueryDsl을 이용한 No offset 구현하기 (0) | 2023.08.06 |
댓글