Projections
- 데이터베이스에서 테이블의 필요한 속성만을 조회하는 것을 말한다.
- 불필요한 컬럼을 조회하는 것을 피함으로써 최적화된 쿼리를 설계할 수 있다.
인터페이스 기반 Projections
public interface ReplyCountInfo {
Long getParentId();
Integer getReplyCount();
}
- 조회를 원하는 컬럼에 대해 get + 컬럼명와 같이 함수를 만들어주면 된다.
- 쿼리를 구성할 때 as 별칭을 사용하여 인터페이스와의 컬럼명을 맞춰줘야 매핑이 잘 진행된다.
- 재귀적으로도 Projections 할 수 있다.
interface PersonSummary {
String getFirstname();
String getLastname();
AddressSummary getAddress();
interface AddressSummary {
String getCity();
}
}
Closed Interface Projections
- 닫힌 프로젝션은 지정한 컬럼만을 프로젝션하는 것을 말한다.
- 지정한 컬럼만 가져오면 되므로 I/O 비용이 감소한다.
Open Interface Projections : 성능 최적화 이점이 없으므로 설명 생략
동작 방식
- ProjectionFactory가 엔티티 클래스를 가져와 프로젝션 인터페이스의 동적 프록시 인터페이스 생성.
- 메소드를 호출하면 동적 프록시의 InvocationHandler가 해당 호출을 가로채서 원본 엔티티에서 해당 속성 값을 찾아서 반환.
// 인터페이스 정의
interface UserInfo {
String getName();
String getEmail();
}
// 프록시 객체 (런타임 생성)
class UserInfoProxy implements UserInfo {
Map<String, Object> columnIndexMap = {
"name" → "~", // 실제 DB 컬럼명이 아닌 별칭 기준
"email" → "~"
};
public String getName() {
return (String) columnIndexMap.get("name"); // 쿼리 결과의 첫 번째 컬럼
}
public String getEmail() {
return (String) columnIndexMap.get("email"); // 두 번째 컬럼
}
}
실제 적용
상황 : 게시글의 댓글을 조회할 때 부모 댓글말 조회하고, 대댓글의 경우 개수만 조회하여 댓글 밑에 ~~개 댓글 더보기와 같은 형식을 하려고 한다.
문제 : 부모 댓글에 대해 자식 댓글의 개수를 사용해야 하므로 group by와 count를 사용해야 했다. 이 때 count에 대한 정보는 Entity에 없으므로 매핑이 되지 않는다.
예제
@Query("""
SELECT c.parent.id as parentId, count(c) as replyCount
FROM StudyComment c
WHERE c.parent.id in ?1
GROUP BY c.parent.id
"""
)
List<ReplyCountInfo> countByParentIdListGroupByParentId(List<Long> parentIdList);
'Spring Boot > JPA' 카테고리의 다른 글
@Transactional 주의 사항 (0) | 2025.02.18 |
---|---|
@Transactional(readOnly = true) 이점 (0) | 2025.02.18 |
Page 객체 응답 시 직렬화 변경 사항 (0) | 2024.12.04 |
임베디드 타입 in JPA (0) | 2024.10.22 |
entity 기본 생성자 in jpa (0) | 2024.10.11 |