@Entity
@Table(name = "bookmark")
@Getter
public class Bookmark {
@Id
@GeneratedValue
@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;
}
이렇게 되어있는 상태에서 u_id와 r_id로 insert하고 싶다.
그런데 엔티티를 설계하려고 보면, User, Review와 같이 클래스 타입이라 u_id, r_id만으로는 엔티티를 생성할 수 없다.
그렇다고 User DB에서 select해오고, Review DB에서 select 해오고.. 이렇게 하자니 굉장한 비효율이 아닌가? 하는 생각에 열심히 서치했다.
findById
실제 DB에 요청해서 엔티티를 가져온다.
정확히 말하면 영속성 컨텍스트의 1차 캐시를 먼저 확인하고 데이터가 없으면 실제 DB에 데이터가 있는지 확인한다.
(지금은 Deprecate된) getById -> (지금은) getReferenceById
엔티티를 직접 반환하는 것이 아니라 프록시만 반환한다.
프록시만 반환하기 때문에 실제로 사용하기 전까지는 DB에 접근하지 않으며, 나중에 프록시에서 DB에 접근하려고 할 때 데이터가 없다면 EntityNotFoundException이 발생한다.
@Transactional
public Long bookmarkReview(Long userId, Long reviewId){
Optional<Bookmark> checkBookmark = bookmarkRepository.findByUserUserIdAndReviewReviewId(userId, reviewId);
if(checkBookmark.isEmpty()){
/**
* 없으면 insert
*/
User user = userRepository.getReferenceById(userId);
Review review = reviewRepository.getReferenceById(reviewId);
Bookmark bookmark = new Bookmark(user, review);
return bookmarkRepository.save(bookmark).getBookmarkId();
} else {
/**
* 이미 있으면 delete
*/
Long bookmarkId = checkBookmark.get().getBookmarkId();
bookmarkRepository.deleteById(bookmarkId);
return 0L;
}
}
'개발 > Spring' 카테고리의 다른 글
Entity와 DTO (0) | 2023.08.02 |
---|---|
@Transactional 동작원리와 public method calls private method에서의 트랜잭션 적용 여부 (0) | 2023.08.02 |
JPA OSIV(Open Session In View)와 성능 최적화 (0) | 2023.07.12 |
@Transactional, JPA dirty checking, readOnly=true 옵션 (0) | 2023.07.12 |
ConnectionPool과 JPA HikariCP 개념 (0) | 2023.07.09 |
댓글