일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- modelmapper
- querydsl
- NoSQL Workbench
- Kotlin
- growpart
- jenkins bitbucket
- docker app
- layout-dialect
- 개발서버
- 윈도우 개발서버
- docker
- push 403
- jenkins window
- EC2
- DynamoDB
- Telegram API
- telegram
- 카카오 알림톡
- 비즈뿌리오
- springboot
- 고정 아이피
- QureyDsl
- thymeleaf
- 알림톡
- rbenv
- docker node
- AWS
- NoArgsConstructor
- spring boot
- jdk upgrade
- Today
- Total
givepro
JPA Specification 활용하여 다중 조건 쿼리문 구현 본문
안녕하세요.
이번 포스팅에서는 JPA Specification에 대해서 다루고자 합니다.
Spring JPA Specification
Spring JPA에서 제공하는 검색 조건을 메서드 형태로 추상화하여 Repository 인터페이스에서
해당 검색 조건을 조합하고 쿼리하기 쉽게 할 수 있는 기능입니다.
WHY?
여러 조건에 대해서 JpaRepository로 구현했을때 복잡해지고 보기 힘들어지는 코드
List<Sample> findAllByHelloIdAndViewerTypeCodeAndDeletedFalseAndValidTrueOrderBySeqAsc(Long helloId, String viewerTypeCode);
위 코드를 보기만해도 머리가 아파지는 느낌이다. (도대체 무슨 조건이 저렇게 많나 싶은)
물론 간단한 조건의 경우는 위의 방식과 같이 처리하지만,
재사용성이 높은, 중복된 코드 등 효율적으로 관리하기 위해서는 다른 방법을 쓰는것이 필요했다.
HOW
public interface SampleRepository extends JpaRepository<Sample, Long>, JpaSpecificationExecutor<Sample> {
}
Repository 인터페이스에 JpaSpecificationExecutor 상속해준다.
import javax.persistence.criteria.Predicate;
public class SampleSpecification {
public static Specification<Sample> of (Long helloId, String viewerTypeCode, boolean valid) {
return (root, query, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.equal(root.get("hello"), helloId));
predicates.add(criteriaBuilder.equal(root.get("viewerType").get("code"), viewerTypeCode));
if (valid) predicates.add(criteriaBuilder.equal(root.get("valid"), Boolean.TRUE));
predicates.add(criteriaBuilder.equal(root.get("deleted"), Boolean.FALSE));
query.orderBy(criteriaBuilder.asc(root.get("seq")));
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
}
}
별도의 Specification 클래스를 만들어주도록 합니다.
관련된 내용을 찾아보면 소스는 많으나 저 코드에 대한 자세한 설명이 부족해서 나름 찾아가봐면서 정리를 해봤습니다.
1. root
영속적 엔티티를 나타내는 쿼리 표현식과 같다. 즉 Sample Entity라고 생각하면 된다.
root.get("hello") → Sample의 hello 필드를 말하는 것
2. query
이름 그대로 작성되는 쿼리로 생각하면 된다. 위에서는 order by 구문을 설정
3. criteriaBuilder
일단 criteria가 뭔지부터 알아야 한다.
Criteria 는 JPQL 의 작성을 도와주는 빌더 클래스이다
javax.persistence.criteria 패키지에 존재
Criteria 쿼리는 빌더(CriteriaBuilder) 필요, EntityManager나 EntityManagerFactory로 생성
Criteria 쿼리 빌더에서 Criteria 쿼리(CriteriaQuery)를 생성
단순하게 말하면 위 Specification에서 쿼리를 생성해주는 빌더라고 생각하면 될 것 같다.
4. Predicate
직역하면 "서술어"라고 합니다. 여기서는 쿼리문의 Where절에 들어가는 조건문이라고 생각하시면 됩니다.
위 코드에서는 조건문을 List로 담고 criteriaBuilder에 담은 조건문을 전달해주는 역할인 것 같습니다.
이전에는 남들이 작성된 코드를 가져와서 사용하다보니 왜 사용하는지에 대해 의문이 있었으나,
최근 프로젝트를 진행하면서 중복된 쿼리문, 재사용성을 위해서 Specification의 필요성이 느끼고 위와 같이 정리를 해봤습니다.
매번 느끼지만 계속해서 뭔가를 해봐야 깨닫는게 많은 것 같습니다.
'백엔드 > SpringBoot' 카테고리의 다른 글
공공데이터 날씨 API 활용 (0) | 2022.10.28 |
---|---|
spring boot jdk upgrade (8 → 11) (0) | 2022.10.28 |
DTO 사용 시 참고사항 (@NoArgsConstructor, Mapper) (0) | 2022.10.27 |
Spring boot QureyDsl 설정 (멀티 모듈) (0) | 2022.10.25 |
애플 로그인 및 탈퇴 과정 (2) | 2022.10.25 |