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를 조회하기 위해 다양한 필드를 두었습니다.
각 필드에는 데이터가 있을 때도 있고 없을 때도 있습니다.
조회 조건 추가
먼저 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 - 실행 오류 정리 (application.yml, SDK, test) (0) | 2024.09.19 |
---|---|
[백엔드] 회원탈퇴(Soft delete) 및 회원복구 (1) | 2024.09.08 |
[벡엔드] 카테고리 Java Enum 활용 (0) | 2024.09.06 |
[면접 후기] 첫 번째 백엔드 면접 후기 및 회고 (0) | 2024.08.21 |
[트러블 슈팅] 엔티티 이름을 User로 지으면 안되는 이유와 해결 방법 (H2 버전 2.x.x) (0) | 2024.01.10 |