- Native Query로 similarity() 계산 -> 정렬 -> ID만 반환함 (Join 없이 ID만)
- JPQL + EntityGraph 활용
: ID 목록으로 author 자동 Join fetch 함.
: JPA는 세 가지 종류가 있음
1. 메서드 이름으로 자동 생성
findByAuthorId(Long authorId)
// JPA가 자동으로 SQL 생성
@Query("SELECT p FROM TherapyPost p WHERE p.deletedAt IS NULL")
// TherapyPost = 자바 클래스명
// deletedAt = 자바 필드명
// JPA가 이걸 SQL로 변환해줌
@Query(value = "SELECT p.id FROM therapy_posts p WHERE p.deleted_at IS NULL",
nativeQuery = true)
// therapy_posts = 실제 테이블명
// deleted_at = 실제 컬럼명
// JPA 변환 없이 그대로 DB로 날아감
문제 1. 페이지네이션
JPA의
Page<>반환을 쓰려면countQuery도 같이 써야함@Query(value = "SELECT p.*, u.* ...", countQuery = "SELECT count(*) ...", nativeQuery = true) Page<TherapyPost> findByRelevance(...)Native Query에서
Page<TherapyPost>로 받으면 JPA가p.*와u.*를 TherapyPost 객체에 맵핑하는걸 보장 못함
JPQL은 JPA가 서버 구조를 알고(어떤필드가 게시글을 나타내는지 등) 만든 쿼리라 맵핑이 보장됨
Native는 JPA가 모르는 쿼리를 날림. 따라서 컬럼 겹치거나 바로바로 맵핑이 안됨
<요약>
Native Query → DB 표현 (p.*, u.*)
Page<TherapyPost> → JPA 표현 (자바 객체)
둘이 언어가 달라서 JPA가 "이 컬럼이 어느 필드야?" 를 모름
→ 매핑 보장 안 됨
그래서 해결책
Native Query → Long(ID)만 반환 ← DB 표현 그대로, 단순한 타입
JPQL → Page<TherapyPost> ← JPA 표현, 매핑 보장
[1단계 native query]
similarity 계산 + 정렬 + 페이지네이션
→ [5, 2, 8, 1] ID 목록 반환
[2단계 JPQL + EntityGraph]
WHERE id IN (5, 2, 8, 1)
→ author JOIN해서 TherapyPost 객체로 매핑해서 반환
첫 번째로, countQuery를 NativeQuery로 추가적으로 날려줘야함
두 번째로, NativeQuery가 가리키는 데이터(u., p.)를 JPA가 맵핑을 못함
문제 2. 매핑 복잡도
native qyery 결과 + TherapyPost + User 컬럼이 섞인 ResultSet
JPA가 이걸 TherapyPost.author 까지 자동 매핑? 보장 안됨
: Java Persistence API
자바 객체와 DB 테이블을 연결해주는 표준 인터페이스
자바 객체 ↔ JPA ↔ DB 테이블
TherapyPost ↔ therapy_posts
즉, 직접 SQL 안써도 자바 객체로 DB를 다룰 수 있음
JPA는 스펙이고 실제 구현체는 하이버네이트임.
: Java Persistence Query Language
JPA에서 쓰는 객체 기준 쿼리 언어
-- SQL (테이블/컬럼 기준)
SELECT * FROM therapy_posts WHERE deleted_at IS NULL
-- JPQL (객체/필드 기준)
SELECT p FROM TherapyPost p WHERE p.deletedAt IS NULL
SQL이랑 생김새가 비슷한데 테이블명 대신 클래스명, 칼럼명 대신 필드명을 사용함. JPA가 이걸 받아서 SQL로 변환하여 DB로 날림