[Java Spring] DB에서 조건 검색 하는 방법 (Specification, Predicate)

2024. 1. 14. 18:46·백엔드/Java + Spring
728x90
반응형

오늘은 스프링JPA에서 DB 조건 검색을 하기 위해 제가 사용했던 코드들을 리뷰해보겠습니다.

 

Repository

@Repository
public interface SubjectRepository extends JpaRepository<Subject, Long>, JpaSpecificationExecutor<Subject> {
}

 

리포지토리는 JpaRepository 사용

Specification을 사용하기 위해 JpaSpecificationExecutor<T>를 extends 해주시면 됩니다.

 

 

Specification, Dto

public class SubjectSpecification {
    public static Specification<Subject> subjectFilter(GetSubjectListRequestDto requestDto) {
        return (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (requestDto.getSubjectId() != null) {
                predicates.add(cb.equal(root.get("subjectId"), requestDto.getSubjectId()));
            }
            if (requestDto.getSubjectName() != null) {
                predicates.add(cb.like(root.get("subjectName"), "%" + requestDto.getSubjectName() + "%"));
            }
            if (requestDto.getProfessor() != null) {
            	Join<Subject, ClassInfo> classInfoJoin = root.join("classInfoList");
                predicates.add(cb.equal(classInfoJoin.get("professor"), requestDto.getProfessor()));
            }
            if (requestDto.getDepartment() != null) {
                predicates.add(cb.like(root.get("department"), "%" + requestDto.getDepartment() + "%"));
            }
            if (requestDto.getMajorClassification() != null) {
                predicates.add(cb.like(root.get("majorClassification"), "%" + requestDto.getMajorClassification() + "%"));
            }
            if (requestDto.getCredit() != null) {
                predicates.add(cb.equal(root.get("credit"), requestDto.getCredit()));
            }
            if (requestDto.getSubjectTarget() != null) {
                predicates.add(cb.like(root.get("subjectTarget"), "%" + requestDto.getSubjectTarget() + "%"));
            }
            return cb.and(predicates.toArray(new Predicate[0]));
        };
    }
}
@AllArgsConstructor
@Getter
@NoArgsConstructor
public class GetSubjectListRequestDto {
    private Long subjectId; //과목 번호
    private String subjectName; //과목 이름
    private String professor; //교수명
    private String department; //개설 학과
    private String majorClassification; //이수 구분(주전공)
    private Double credit; //학점
    private String subjectTarget; //수강 대상
}

 

 

요청 예시

RequestDto에는 Subject를 조회하기 위해 다양한 필드를 두었습니다.

각 필드에는 데이터가 있을 때도 있고 없을 때도 있습니다.

 

ex)&nbsp; JSON 형식 http 요청 예시

 

 

조회 조건 추가

먼저 Predicate 리스트를 생성합니다.

RequestDto 필드에 값이 들어가 있는 조건들을 기준으로 조회하기 위해 if문에서 필드 값에 대한 null 검사를 해주고

Predicate 리스트에 조회할 조건을 추가합니다.

predicates.add(cb.equal(root.get("subjectId"), requestDto.getSubjectId()));
// DB에 있는 subectId와 Dto의 subjectId가 동일하다면 조회

predicates.add(cb.like(root.get("subjectName"), "%" + requestDto.getSubjectName() + "%"));
// DB에 있는 subjectName이 Dto의 subjectName을 포함하는 문자열인 경우 조회
// %는 무작위 문자열을 의미합니다.

 

 

Join

코드를 보다보면 중간에 나머지 코드들는 다른 코드가 있습니다.

Join<Subject, ClassInfo> classInfoJoin = root.join("classInfoList");
predicates.add(cb.equal(classInfoJoin.get("professor"), requestDto.getProfessor()));

 

이 코드는 Subject와는 다른 엔티티인 ClassInfo라는 엔티티에서 professor에 대한 정보를 기준으로 조회하기 위해 Subject에서 ClassInfo를 join하여 ClassInfo 필드의 교수명과 Dto의 교수명을 비교한 것입니다.

 

root, query, cb

return (root, query, cb) -> {}

 

root, query, cb는 JPA Criteria API에서 사용되는 주요 구성 요소입니다.

 

root

  • 영속적 엔티티를 표시하는 데 사용
  • root.get("subjectId")와 같이 사용하여 엔티티의 특정 속성에 접근 가능

 

query

  • Criteria 쿼리의 인스턴스
  • select 절, from 절, where 절 등을 정의

 

cb

  • CriteriaBuilder의 인스턴스
  • 쿼리를 구성하는 데 필요한 다양한 메서드를 제공
 

 

결과

 

위에 있는 요청 예시에서 필드 값들을 바꿔서 요청을 보냈고 성공적으로 원하던 데이터를 응답 받았습니다.

728x90
반응형

'백엔드 > Java + Spring' 카테고리의 다른 글

[백엔드] Blog - 모든 엔티티 생성 시간, 업데이트 시간 설정하기 @CreatedDate, @LastModifiedDate, BaseEntity  (1) 2024.09.24
[백엔드] Blog - 전역 예외 커스텀 처리하기 @RestControllerAdvice, @ExceptionHandler  (1) 2024.09.24
[백엔드] Blog - 실행 오류 정리 (application.yml, SDK, test)  (0) 2024.09.19
[백엔드] 회원탈퇴(Soft delete) 및 회원복구  (1) 2024.09.08
[벡엔드] 카테고리 Java Enum 활용  (0) 2024.09.06
'백엔드/Java + Spring' 카테고리의 다른 글
  • [백엔드] Blog - 전역 예외 커스텀 처리하기 @RestControllerAdvice, @ExceptionHandler
  • [백엔드] Blog - 실행 오류 정리 (application.yml, SDK, test)
  • [백엔드] 회원탈퇴(Soft delete) 및 회원복구
  • [벡엔드] 카테고리 Java Enum 활용
dev_ares
dev_ares
대학에서 컴퓨터공학을 전공하고 있는 학생입니다.
    반응형
    250x250
  • dev_ares
    노트
    dev_ares
  • 전체
    오늘
    어제
    • 분류 전체보기 (188)
      • IT 트랜드 (2)
      • 백엔드 (18)
        • Java + Spring (8)
        • Kotlin + Spring (5)
        • 백엔드 (5)
      • 프론트엔드 (1)
        • React (1)
      • 대외활동 (17)
        • 42서울 (17)
      • 백준 (6)
        • Java (2)
        • C++ (3)
      • 전공 (121)
        • 객체지향프로그래밍 (17)
        • 자료구조 (23)
        • 리눅스시스템관리 (16)
        • 컴퓨터구조 (25)
        • 네트워크 (25)
        • 데이터베이스 (15)
        • 기타 전공 (0)
      • 프로그래밍 언어 (18)
        • Java (5)
        • Swift (4)
        • C++ (1)
        • Kotlin (8)
      • 기타 (4)
      • 공군 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    42서울
    상속
    반복자
    C++
    백준
    사설 문제
    자바
    오블완
    메모리 계층 구조
    단일 사이클
    데이터패스
    컴퓨터구조
    컴퓨터 구조 및 설계
    리눅스
    코틀린
    추가 문제
    자료구조
    컴공 포트폴리오
    티스토리챌린지
    명령어
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
dev_ares
[Java Spring] DB에서 조건 검색 하는 방법 (Specification, Predicate)
상단으로

티스토리툴바