검색기능 구현
- build.gradle 추가부분
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
def querydslSrcDir = 'src/main/generated'
clean{
delete file(querydslSrcDir)
}
tasks.withType(JavaCompile){
options.generatedSourceOutputDirectory = file(querydslSrcDir)
}
● 리스트페이지에 검색 화면 구성
<div class ="container-fluid">
<form action="/board/list" class="d-flex" role="search" >
<select class="form-select form-select-sm" id="inputGroupSelect01" name="type" style="width: 70%; margin-right: 20px">
<option th:selected="${pgvo.type == null ? true : false}" >Choose...</option>
<option th:value="t" th:selected="${pgvo.type == 't' ? true : false}" >title</option>
<option th:value="w" th:selected="${pgvo.type == 'w' ? true : false}">writer</option>
<option th:value="c" th:selected="${pgvo.type == 'c' ? true : false}">content</option>
<option th:value="tw" th:selected="${pgvo.type == 'tw' ? true : false}" >title + writer</option>
<option th:value="wc" th:selected="${pgvo.type == 'wc' ? true : false}">writer + content</option>
<option th:value="tc" th:selected="${pgvo.type == 'tc' ? true : false}">title + content</option>
<option th:value="twc" th:selected="${pgvo.type == 'twc' ? true : false}">all</option>
</select>
<input class="form-control me-2" name="keyword" type="search" placeholder="Search..." aria-label="Search" th:value="${pgvo.keyword }" >
<input type="hidden" name="pageNo" value="1">
<button type="submit" class="btn btn-success position-relative">
Search
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
[[${list.totalElements }]]
<span class="visually-hidden">unread messages</span>
</span>
</button>
</form>
</div>
● PagingVO에 타입 , 키워드를 추가해주고 생성자도 추가
private String type;
private String keyword;
public PagingVO(Page<BoardDTO> list, int pageNo, String type , String keyword){
this(list,pageNo);
this.type = type;
this.keyword = keyword;
}
● 컨트롤러 list부분에 type과 keyword를 파라미터로 받을 수 있도록하고 list와 pgvo에 추가해줌.
@GetMapping("/list")
public void list(Model model,
@RequestParam(value = "pageNo", defaultValue = "0", required = false) int pageNo,
@RequestParam(value = "type", required = false) String type,
@RequestParam(value = "keyword",required = false) String keyword){
pageNo = (pageNo == 0 ? 0 : pageNo - 1);
Page<BoardDTO> list = boardService.getList(pageNo,type,keyword); // type, keyword 추가해서 서비스임플로 보내기
PagingVO pgvo = new PagingVO(list, pageNo,type,keyword);
model.addAttribute("list", list);
model.addAttribute("pgvo", pgvo);
}
● type,keyword,pageable을 받아서 Page<Board> list를 리턴받는 BoardCustomRepository 인터페이스를 생성
public interface BoardCustomRepository {
Page<Board> serachBoards(String type, String keyword, Pageable pageable);
}
- 구현 타입을 배열로만들어서 나눈다음 switch case를 이용해서 타입별 포함하는지 확인하는 구문구현
이후 구현한 조건문을 이용해서 페이징
public class BoardCustomRepositoryImpl implements BoardCustomRepository{
private final JPAQueryFactory queryFactory;
public BoardCustomRepositoryImpl(EntityManager em) {
this.queryFactory = new JPAQueryFactory(em);
}
// 실제 구현
@Override
public Page<Board> serachBoards(String type, String keyword, Pageable pageable) {
// 조건이 많을 경우
// select * from baord where
// isDel = 'n' and title like '% aaa %'
// BooleanExpression condition = board.isDel.eq('N');
BooleanExpression condition = null;
// 동적 검색 조건 추가
if(type != null && keyword != null){
String[] typearr = type.split("");
// 이전 선행 조건이 있다면...
BooleanExpression dynamicCondition = null;
for(String t : typearr){
switch (t) {
case "t":
dynamicCondition = (dynamicCondition == null) ?
board.title.containsIgnoreCase(keyword) : dynamicCondition.or(board.title.containsIgnoreCase(keyword));
break;
case "w":
dynamicCondition = (dynamicCondition == null) ?
board.writer.containsIgnoreCase(keyword) : dynamicCondition.or(board.writer.containsIgnoreCase(keyword));
;
break;
case "c":
dynamicCondition = (dynamicCondition == null) ?
board.content.containsIgnoreCase(keyword) : dynamicCondition.or(board.content.containsIgnoreCase(keyword));
break;
}
}
if(dynamicCondition != null){
condition = dynamicCondition;
}
}
// 쿼리 작성 및 페이징 적용
List<Board> result = queryFactory
.selectFrom(board)
.where(condition)
.orderBy(board.bno.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();
// 검색된 데이터의 전체 개수 조합
long total = queryFactory
.selectFrom(board)
.where(condition)
.fetch().size(); // .fetchCount()
return new PageImpl<>(result, pageable, total);
}
● 생성한 type,keyword,pageable을 받아 Page list를 리턴하는 메서드를 이용해서 ServiceImpl 수정 검색기능을 구현.
@Override
public Page<BoardDTO> getList(int pageNo, String type, String keyword) {
// pageNo = 0부터 시작
// 0 => limit 0,10 , 1=> limit 10,10
Pageable pageable = PageRequest.of(pageNo,10,Sort.by("bno").descending());
// type, keyword , pageable 값을 주고, Page<Board> list 리턴 받는 메서드 생성
Page<Board> list = boardRepository.serachBoards(type,keyword,pageable);
Page<BoardDTO> boardDTOList = list.map(b -> convertEntityToDto(b));
return boardDTOList;
}
● 페이지네이션 th:href 부분에 추가
type=${pgvo.type},keyword=${pgvo.keyword}
이러면 전체적인 CURD 게시판은 끝
'boot_JPA 수업 정리' 카테고리의 다른 글
Boot_JPA 4일차 (1) | 2024.11.25 |
---|---|
Boot_JPA 3일차 (0) | 2024.11.22 |
Boot_JPA 2일차 (3) | 2024.11.21 |
Boot_JPA 1일 (1) | 2024.11.20 |