[JpaRepository 쿼리 기능 : 테이블 객체로 자동 쿼리 생성하기]
- Repository는 MarkerInterface로 특별한 기능은 없음
- Repository ~ JpaRepository까지는 @NotRepositoryBean이 붙어있는 인터페이스
- JpaRepository<Entity,ID> 붙이면 알맞게 프로그래밍 된 SimpleJpaReository 구현체 빈이 등록됨
- @NotRepositoryBean된 상위 인터페이스들의 기능을 포함한 구현체가 프로그래밍됨
(@NotRepositoryBean = 빈생성 막음)
- @SpringBootApplication을 통해 자동으로 붙여지는 @EnableJpaRepositories의 JpaRepositoriesRegistrar를 통해서 등록됨!
- JpaRepositoriesRegistrar 는 ImportBeanDefinitionRegistrar 의 구현체
- ImportBeanDefinitionRegistrar 는 프로그래밍을 통해 빈을 주입해줌
JpaRepository 효율적으로 사용하는 방법
1. Optional 제거하기
- Spring Data JPA의 findByXX 메서드는 기본적으로 Optional을 반환
- 이로 인해 비즈니스 로직에서 Optional 처리를 위한 추가적인 작업이 필요하게 되는데, 이럴 때 default 메서드를 활용 가능
2. 메서드명 간소화하기
- Spring Data JPA를 사용하다보면 복잡한 쿼리 때문에 메서드명이 길어져 가독성을 해치는 경우가 있음
- 이럴 때도 default 메서드를 활용하면 긴 메서드명을 간결하고 명확하게 표현 가능
3. 비즈니스 로직 통합
- 여러 기본 제공 메서드를 하나의 고차 작업으로 결합가능
- 다만 Spring Data JPA의 Repository는 Data Access Layer의 일부로, 데이터베이스와의 상호작용만을 담당하는 것이 일반적이기 때문에 이 부분은 서비스 레이어에서 처리하는 것이 일반적!
[Pageable & Sorting]
Pageable
- Pageable 인터페이스를 구현한 PageRequest 객체를 만들거나 얻음
- PageRequest 객체를 repository 메소드에 인자로 전달
- PageRequest 객체는 요청된 페이지 숫자와 페이지 사이즈를 넘김으로서 만듦 (페이지 숫자는 0부터 시작)
- findAll(Pageable pageable) 메소드는 기본적으로 Page 객체를 리턴하지만
- 커스텀 메소드를 통해 페이지네이션된 데이터를 Page , Slice 또는 List 의 타입으로 받을 수 있음
- Page 인스턴스는 Product의 목록 뿐 아니라 페이징할 수 있는 전체 목록의 숫자도 알고 있음
- 이를 실행하기 위해 추가적으로 쿼리 작업이 들어감
- 이러한 작업에 대한 비용을 방지하기 위해, 우리는 대신 Slice나 List로 반환 받을 수 있음
- Slice는 단지 다음 slice가 가능한지 아닌지만 알고 있음
Sorting
- 쿼리 결과를 정렬하기 위해서 Sort 객체를 메소드에 전달
- 정렬과 페이지네이션을 둘다 하고 싶다면 정렬에 대한 디테일 정보를 PageRequest 객체에 전달!
- 페이징 없이 정렬만 하려는 경우 findAll(Sort sort) 메서드와 같이 Sort 객체만 파라미터로하는 메서드를 작성하면 됨
- CRUD에 관련된 연산이 문자열로 이루어진 경우, Run time시에 해당 에러를 확인가능
- Compile 단계에서 Type-Check가 불가능하여, 장애 Risk가 상승!!!
▼ ▼ ▼ ▼ ▼ ▼ ▼ ▼
[QueryDSL]
- JPQL과 같이, 쿼리문을 문자열로 작성하여, Compile 시에 Type-Check가 되지 않았던 문제를 해결하기 위해 나온 프레임워크
- 정적 타입을 이용하여, SQL과 같은 쿼리를 코드 형태로 생성할 수 있도록 해주는 오픈소스 빌더 API
- SQL문을 직접 하드코딩 하는 것이 아닌, 코드 형태로 작성하는 것이 특징
- 쿼리가 문자열 형태가 아닌, 함수 형태로 조합되어 최종 결과를 반환
- @Entity로 등록된 모든 클래스에 대한 Q-객체를 만들고, 그 안에 멤버 변수로 정의된 컬럼들에 대한 연산들을 메서드 형태로 Compile-time에 생성
- 즉, Compile-time에 에러가 식별되기 때문에 장애 Risk를 크게 줄일 수 있음
- Entity의 매핑정보를 활용하여 쿼리에 적합하도록 쿼리 전용 클래스(Q클래스)로 재구성해주는 기술
- JPAQueryFactory을 통한 Q클래스를 활용할 수 있는 기능들을 제공
- JPAQueryFactory
- 재구성한 Q클래스를 통해 문자열이 아닌 객체 또는 함수로 쿼리를 작성하고 실행하게 해주는 기술
- JPAQueryFactory 사용을 위해 JPAQueryFactory에 entityManager를 주입해서 Bean으로 등록해줘야 함
- Spring boot 3.x에서 QueryDSL 연동하기
- build.gradle의 dependencies에 아래와 같이 추가
Q-객체
- JPAAnnotationProcessor가 컴파일 시점에 @Entity와 @Embeddedable과 같은 어노테이션이 걸린 클래스에 대해, 미리 생성하는 쿼리 객체
- 해당 객체에 쿼리문을 메서드 형태로 호출하여 SQL문을 짜듯이 코드로 쿼리문 작성이 가능