- 이번에 게시판 카테고리를 구현하면서 기존에 Repository에 쿼리를 직접 만들어 사용하던 방식 대신 좀 더 편하고 가독성도 좋은 방식을 알게되어 해당 방식으로 코드를 수정하게 되었습니다.
- 우선 기존에 사용하던 코드는 아래와 같습니다.
if(category.equals("screenshot")) {
model.addAttribute("boards", boardRepository.findAllByCategory(CategoryType.SCREENSHOT, pageable));
return"index";
}
if(searchKeyword == null || searchKeyword.isBlank()) {
model.addAttribute("boards", boardRepository.findAll(pageable));
}
if(searchType.equals("nickname")) {
model.addAttribute("boards",
boardRepository.findByUserNicknameContaining(searchKeyword, pageable));
} else {
model.addAttribute("boards", boardRepository.findByTitleContaining(searchKeyword, pageable)); }
- 각각의 변수를 @RequestParam으로 받아서 조건문을 통해 분기해가며 데이터를 필터링하는 방식입니다.
📝 BoardRepository
- JPA Specification을 사용하기 위해 우선 아래와 같이 해당 Repository에서 JpaSpecificationExecutor를 상속받아야 합니다.
package com.cos.blog.repository;
...
// @Repository
public interface BoardRepository extends JpaRepository<Board, Long>, JpaSpecificationExecutor<Board>{
...
}
📝 BoardSpecification
- 다음으로 내가 원하는 조건에 따라 설정한 각각의 함수를 포함하고 있는 클래스를 생성해주었습니다.
package com.cos.blog.specification;
...
public class BoardSpecification {
// 글 제목에 따른 검색
public static Specification<Board> searchTypeTitle(String searchKeyword) {
return (root, query, criteriaBuilder) -> criteriaBuilder.like(root.get("title"), "%" + searchKeyword + "%");
}
// 작성자에 따른 검색
public static Specification<Board> searchTypeWriter(String searchKeyword) {
return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("user").get("nickname"), searchKeyword);
}
// 카테고리 구분
public static Specification<Board> equalCategory(String category) {
return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("category"), category);
}
// 추천 수에 따른 구분
public static Specification<Board> recGreaterThan(int recommendCount) {
return (root, query, criteriaBuilder) -> criteriaBuilder.greaterThan(root.get("recommendCount"), recommendCount);
}
}
📝 BoardController
- 실제 사용할 때에는 위에서 정의한 함수를 원하는대로 조합하여 다중 조건 쿼리를 만들 수 있습니다.
Specification<Board> spec = (root, query, criteriaBuilder) -> null;
if(!category.isEmpty()) {
if(category.equals("popular")) {
spec = spec.and(BoardSpecification.recGreaterThan(30));
} else {
spec = spec.and(BoardSpecification.equalCategory(category));
}
}
if(!searchType.isEmpty()) {
if(searchType.equals("title")) {
spec = spec.and(BoardSpecification.searchTypeTitle(searchKeyword));
} else {
spec = spec.and(BoardSpecification.searchTypeWriter(searchKeyword));
}
}
model.addAttribute("boards", boardRepository.findAll(spec, pageable));
- 기존 코드보다 훨씬 깔끔하고 보기도 좋은 것 같았습니다.
💡 알게 된 점
- JPA Specification을 사용하여 다중 조건 검색 구현
'🚗 Backend Toy Project > 스프링 부트 게시판' 카테고리의 다른 글
[스프링부트 게시판] 36. 관리자 페이지 - 게시글 통계 (0) | 2022.10.26 |
---|---|
[스프링부트 게시판] 35. 관리자 페이지 - 회원 관리 (0) | 2022.10.24 |
[스프링부트 게시판] 34. 사용자 프로필 이미지 추가 (0) | 2022.09.27 |
[스프링부트 게시판] 33. 댓글 알림 기능 (1) | 2022.09.23 |
[스프링부트 게시판] 32. 이전에 봤던 글 표시 (0) | 2022.09.17 |