토이프로젝트를 만들면서 연관관계가 있는 Entity 저장 시 고려한 getById() 와 findById()에 대해 정리한 글이다.

ERD 를 보면 Pay Entity 저장 시 reservation_id 만 넣어주면 될 것 같지만 ORM에선 Reservation Entity를 넣어줘야한다.
이 때 Pay에 맵핑해 줄 Reservation Entity를 찾기 위해 findById() 와 getById()를 사용할 수 있다.
Retrieves an entity by its id.
Returns: the entity with the given id or Optional#empty() if none found.
CrudRepository interface의 finById()는 DB를 바로 조회해서 Entity를 찾고 Optional를 반환한다.
Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is implemented this is very likely to always return an instance and throw an javax.persistence.EntityNotFoundException on first access. Some of them will reject invalid identifiers immediately.
JpaRepository interface의 getById()는 EntityManager.getReference()를 통해 Entity를 가져온다. 이 메서드는 호출 시에는 lazy loading으로 Proxy Entity를 가져오고 Entity 속성에 접근하는 순간에서야 DB에서 실제 Entity를 가져온다.
@Test
@Transactional
public void findById_test() {
PaySaveRequestDto paySaveRequestDto = PaySaveRequestDto.builder()
.payType("MONEY")
.amount(1000)
.reservationId(1L)
.build();
Reservation reservation = reservationRepository.findById(paySaveRequestDto.getReservationId())
.orElseThrow();
payRepository.save(paySaveRequestDto.toEntity(reservation)).getId();
}
@Test
@Transactional
public void getById_test() {
PaySaveRequestDto paySaveRequestDto = PaySaveRequestDto.builder()
.payType("MONEY")
.amount(1000)
.reservationId(1L)
.build();
Reservation reservation = reservationRepository.getById(paySaveRequestDto.getReservationId());
payRepository.save(paySaveRequestDto.toEntity(reservation)).getId();
}
Hibernate: select reservatio0_.reservation_id as reservat1_9_0_, ... from reservation reservatio0_ where reservatio0_.reservation_id=?
Hibernate: insert into pay (created_date, modified_date, amount, pay_type, reservation_id) values (?, ?, ?, ?, ?)

Pay Entity insert 시 Reservation 정보를 저장하기 위해 finById()를 호출하면 Reservation 테이블에 접근하여 Reservation Entity를 가져온 후 Pay 테이블에 insert 하게 된다.
Hibernate: insert into pay (created_date, modified_date, amount, pay_type, reservation_id) values (?, ?, ?, ?, ?)

getById()를 사용하면 Pay Entity insert 시 Reservation Proxy 객체를 사용하므로 insert 문만 실행된다.
위의 경우라면 findById() 대신 getById()를 사용을 고려해보자.