1. 검색기능 - SELECT
resources/templates/list.html의 검색하기 버튼을 누르면 /board/search로 GET method가 요청된다. 요청이 가면 controller에서는 boardService.searchPost(keyword) method를 이용해 해당하는 DTO만 SELECT하게 하고, 받아온 DTO list를 model에 addAttribute한 후 return하자.
1) Controller
/src/main/java/com/example/testcompose/controller/BoardController.java
package com.example.testcompose.controller;
import com.example.testcompose.dto.BoardDto;
import com.example.testcompose.service.BoardService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestParam;
import lombok.AllArgsConstructor;
import java.util.List;
@Controller
@AllArgsConstructor
public class BoardController{
private BoardService boardService;
...
@GetMapping("/board/search")
public String search(@RequestParam(value = "keyword") String keyword, Model model){
List<BoardDto> boardDtoList = boardService.searchPost(keyword);
model.addAttribute("boardList", boardDtoList);
return "board/list.html";
}
}
- annotation
@RequestParam
query에 parameter로 넘긴 값을 가져오는 것이다. 위 코드는 /board/search?keyword=asdf 이렇게 넘어왔을 때 keyword에 해당하는 값만 가져온다.
*** RequestParam vs PathVariable
RequestParam은 url query에 있는 값을, PathVariable은 url 변수에 있는 값을 처리할 때 사용한다.
즉, RequestParam은 /localhost/main?keyword=asdf 이런 형태를, PathVariable은 /localhost/main/post/2 이런 형태를 처리할 때 사용한다.
2) Service
keyword로 받은 값으로 boardRepository에서 검색한 후 BoardEntityList를 넘겨주는 boardRepository.findByTitleInclude() method를 호출하자. 그리고 이전 포스트처럼 boardEntityList를 boardDtoList로 바꾸어서 리턴하자.
/src/main/java/com/example/testcompose/service/BoardService.java
package com.example.testcompose.service;
import com.example.testcompose.dto.BoardDto;
import com.example.testcompose.domain.repository.BoardRepository;
import com.example.testcompose.domain.entity.BoardEntity;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@AllArgsConstructor
@Service
public class BoardService {
private BoardRepository boardRepository;
...
@Transactional
public List<BoardDto> searchPost(String keyword){
List<BoardEntity> boardEntityList = boardRepository.findByTitleContaining(keyword);
List<BoardDto> boardDtoList = new ArrayList<>();
if(boardEntityList.isEmpty()) return boardDtoList;
for(BoardEntity boardEntity : boardEntityList){
boardDtoList.add(this.convertEntity2Dto(boardEntity));
}
return boardDtoList;
}
private BoardDto convertEntity2Dto(BoardEntity boardEntity){
return BoardDto.builder()
.id(boardEntity.getId())
.title(boardEntity.getTitle())
.content(boardEntity.getContent())
.writer(boardEntity.getWriter())
.createdDate(boardEntity.getCreatedDate())
.build();
}
}
3) repository
/src/main/java/com/example/testcompose/service/BoardService.java
package com.example.testcompose.domain.repository;
import com.example.testcompose.domain.entity.BoardEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface BoardRepository extends JpaRepository<BoardEntity,Long>{
List<BoardEntity> findByTitleContaining(String keyword);
}
- import
List를 사용하기 위해 java.util.List를 import하자.
- 내용
JpaRepository method 이름으로 내가 원하는 query를 만들 수 있다. findBy 이후의 부분은 SQL에서 WHERE절에 해당한다. 즉, findByTitle은 Title로 검색하는 것이고 Containing은 Like 검색이다. StartsWith, EndsWith, IgnoreCase, Not 등 여러 옵션이 있다.
https://www.baeldung.com/spring-jpa-like-queries
4) 테스트
test를 검색하면 test1, test2가 둘 다 나오고 test1만 검색하면 test1이 나오는 것을 볼 수 있다.
2. Paging
pageable interface를 이용해 구현 가능하다.
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/PageRequest.html