[JPA] getById() 와 findById()

du·2022년 6월 6일
0

JPA

목록 보기
1/1

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

Pay 와 Reservation ERD

ERD 를 보면 Pay Entity 저장 시 reservation_id 만 넣어주면 될 것 같지만 ORM에선 Reservation Entity를 넣어줘야한다.
이 때 Pay에 맵핑해 줄 Reservation Entity를 찾기 위해 findById() 와 getById()를 사용할 수 있다.

Optional findById(ID id)

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를 반환한다.

T getById(ID id)

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를 가져온다.

예시

finById() 테스트 코드

    @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();
    }

getById() 테스트 코드

    @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 문만 실행된다.

결론

  1. ID에 해당하는 객체가 무조건 존재한다는 것을 보장할 수 있는 경우
  2. 해당 Entity의 다른 정보에 접근하지 않음(사용하지 않음)
  3. 단순히 ID를 통한 맵핑정보가 필요

위의 경우라면 findById() 대신 getById()를 사용을 고려해보자.

참고 자료

0개의 댓글