🏷️ 데이터를 가져오는 방식
✅ findById
Optional<T> findById(ID id)
▪️ Optional<T>: 조회된 엔티티를 Optional로 감싼 반환 타입입니다. Optional은 엔티티가 존재하지 않을 수도 있는 경우에 사용됩니다.
▪️ ID: 조회할 엔티티의 식별자(ID) 타입입니다.
▪️ 조회된 엔티티 객체를 Optional로 감싸서 반환합니다.
▪️ CrudRepository와 JpaRepository 인터페이스에서 모두 제공되는 메소드입니다
✅ getReferenceById
public T getReferenceById(ID id)
▪️ T: 반환 타입으로 엔티티의 클래스 타입입니다.
▪️ ID: 조회할 엔티티의 식별자(ID) 타입입니다.
▪️ 엔티티가 영속성 컨텍스트에 없으면 EntityNotFoundException이 발생할 수 있습니다.
▪️ JpaRepository 인터페이스에서만 제공됩니다.
▪️ 데이터 가져오는 방식
- 지연로딩(Lazy Loading) : 엔티티를 실제로 사용할 때까지 데이터베이스 조회를 지연합니다.
- 실제 엔티티 객체가 필요한 시점에서는 프록시 객체가 아닌 실제 엔티티를 반환합니다. 처음에는 Proxy객체로 가지고 있습니다.
✔️ 정리
우선 getReferenceById 같은 경우 단순히 T(Entity Type)만을 반환해 주고, FindById()는 Optional<T> (Optional <Entity>) 타입으로 존재하는지 안 하는지를 Optional 하게 제공해주고 있습니다.
🏷️ 테스트 코드
✅ findById
@Test
public void testSelect(){
Long member_no = 13L;
Optional<Member> result = memberRepository.findById(member_no);
System.out.println("=============================");
if(result.isPresent()){
Member member = result.get();
System.out.println(member);
}
}
결과
select
m1_0.member_no,
m1_0.member_from_social,
m1_0.member_id,
m1_0.member_nickname,
m1_0.member_password
from
member m1_0
where
m1_0.member_no=?
=============================
Member(member_no=5, member_id=user5, member_password=123123123, member_nickname=사용자5, member_from_social=false)
✅ getReferenceById
@Test
@Transactional
public void testSelect(){
Long member_no = 5L;
Member result_get = memberRepository.getReferenceById(member_no);
System.out.println("=============================");
System.out.println(result_get);
}
결과
=============================
Hibernate:
select
m1_0.member_no,
m1_0.member_from_social,
m1_0.member_id,
m1_0.member_nickname,
m1_0.member_password
from
member m1_0
where
m1_0.member_no=?
Member(member_no=5, member_id=user5, member_password=123123123, member_nickname=사용자5, member_from_social=false)
✔️ 결괏값에 따른 차이
findById()의 경우 "===================="가 findByID가 즉시 실행되고서 출력됩니다. 하지만 getReferenceById()의 경우 member가 필요하다는 것을 알고서 proxy 객체가 그제야 Select문을 실행시키고 있습니다. 하지만 위의 코드에서는 getReferenceById()의 특징이 완전하게 설명되지는 않았습니다. 그래서 아래와 같은 코드를 실행을 시켜보게 되면
@Test
@Transactional
public void testSelect(){
Long member_no = 5L;
Member result_get = memberRepository.getReferenceById(member_no);
System.out.println("=============================");
System.out.println(result_get.getMember_no());
}
=============================
5
이런 결괏값이 나오게 되면서 SQL문을 실행하지 않습니다. 이처럼, getReferenceById를 통해서 ID값만을 가져오고 해당 객체의 ID값만 접근하게 된다면, 해당 Proxy가 참조값을 가지고 있을 수 있습니다. 만약 해당 proxy가 존재하지 않는다면, EntityNotFoundException 이 발생하게 됩니다.
🏷️ 결론
FindById()는 무조건 해당 SQL을 곧바로 실행하고, getReferenceById()는 함수를 호출하고서, 실제로 그 데이터를 출력하거나 사용할 때 SQL이 실행됩니다. (다만, ID값을 호출할 경우 SQL이 필요하지 않습니다.)
일반적인 상황에서는 FindById()를 통해 Optional 한 값을 활용하여 예외처리를 진행하는 것이 좋아 보입니다. 단순히, Entity의 ID값만 필요한 상황이라면, getReferenceById()를 통해 Select문이 실행되는 처리를 제외할 수 있으므로 getReferenceById()를 통해 처리하는 것도 고려하는 것이 좋을 것 같습니다.
📖 Reference
'코딩 공부 > web & Java' 카테고리의 다른 글
[Java] DTO를 Record로 만드는 이유 (0) | 2024.04.17 |
---|---|
[Java] Lombok (0) | 2024.03.10 |
[JPA] JPA Auditing (0) | 2024.02.11 |
[Java] Optional (1) | 2024.01.27 |
[Java] 함수형 인터페이스(Functional Interface) (1) | 2024.01.21 |