보글보글 개발일지
article thumbnail
반응형

이번 팀 프로젝트의 주제는, 온라인 기프티콘 장터를 만드는 것이다. 나는 지난 학기 데이터베이스 수업 프로젝트에서 백엔드 역할을 못했기에, 이번이 직접 백엔드를 구현하는 제대로 된 첫 프로젝트라고 할 수 있다. 그래서 스프링 잘하는 멋쟁이 동기한테 도움을 많이 받았고, 내가 드디어 검색 구현을 스스로 구현했다. 완벽한 코드는 아니지만, 까먹지 않기 위해 글을 남긴다.

SearchDTO.java

@Data
@NoArgsConstructor   // 기본 생성자
@AllArgsConstructor   // 모든 인자가 있는 생성자
public class SearchDTO {

    @NotBlank(message = "검색어를 입력하세요.")
    private String searchKind; //어떤 종류의 검색어인지?
    private String searchWhat; //어떤 검색어인지?

}

search.HTML

<section style="margin-top: 40px;">
    <h2>
        검색
    </h2>
    <form th:object="${searchDTO}" th:action="@{/search}" method="post">
        <div style="text-align: center; margin: 0 auto">
            <div th:if="${#fields.hasGlobalErrors()}">
                <p class="field-error" th:each="err : ${#fields.globalErrors()}" th:text="${err}">
                    글로벌 오류 메시지</p>
            </div>
            <select th:field="*{searchKind}">
                <option value="category">카테고리</option>
                <option value="itemname">상품명</option>
                <option value="brand">브랜드</option>
            </select>
            <input type="text" placeholder="검색어를 입력해주세요." th:field="*{searchWhat}">
            <div class="field-error" th:errors="*{searchWhat}">검색어를 입력 하세요</div>

            <button id="searchBtn" type="submit" class="button-18">검색</button>
        </div>
    </form>

우선 searchDTO 객체안에 searchKind, searchWhat 변수를 담을 거다!

select문을 통해서 value에 값을 담는다. 그리고 그 옆에 입력을 받아 searchWhat 변수에 담아준다.

html은 일단 다 꾸미지 않아서 이렇게 뜬다.

ItemRepository.java

    public List<Gifticon> searchByBrand(String str) {
        return em.createQuery("select g from Gifticon as g where g.brand.name = :searchWhat", Gifticon.class)
                .setParameter("searchWhat", str)
                .getResultList();
    }
    public List<Gifticon> searchByCategory(String str) {
        return em.createQuery("select g from Gifticon as g where g.category.name = :searchWhat", Gifticon.class)
                .setParameter("searchWhat", str)
                .getResultList();
    }
    public List<Gifticon> searchByItem(String str) {
        return em.createQuery("select g from Gifticon as g where g.name = :searchWhat", Gifticon.class)
                .setParameter("searchWhat", str)
                .getResultList();
    }

createQuery를 통해서 쿼리를 생성했다. JPA를 처음 써보았는데, 상당히 편리하다.

:searchWhat는 내가 html에서 보내준 검색어가 저장되어있다. 해당 검색어와 일치하는 브랜드나 카테고리나 상품명이 있으면, 리스트에 담아서 리턴한다.

ItemService.java

    public List<Gifticon> searchByBrand(String str){
        return itemRepository.searchByBrand(str);
    }
    public List<Gifticon> searchByCategory(String str){
        return itemRepository.searchByCategory(str);
    }
    public List<Gifticon> searchByItem(String str){
        return itemRepository.searchByItem(str);
    }

여기서는 그냥 아이템 레포에 저장되어있는 함수를 호출한다. 연결을  서비스-->레포로 해둬서 이렇게 코드를 구현하였다.

HomeController.java

    @GetMapping("/search")
    public String getSearch(Model model) {
        model.addAttribute("searchDTO", new SearchDTO());
        return "search/search";
    }
    

    @PostMapping("/search")
    public String postSearch(@Validated @ModelAttribute("searchDTO") SearchDTO searchDTO, BindingResult bindingResult,
                             HttpServletRequest request, Model model) {

        if(bindingResult.hasErrors()) {   // 필드 오류
            return "search/search";
        }
        String searchKind = searchDTO.getSearchKind();
        String searchWhat = searchDTO.getSearchWhat();
        if(searchKind.equals("brand")){
            List<Gifticon> gifticons = itemService.searchByBrand(searchWhat);
            model.addAttribute("gifticons", gifticons);
        }
        else if(searchKind.equals("category")){
            List<Gifticon> gifticons = itemService.searchByCategory(searchWhat);
            model.addAttribute("gifticons", gifticons);
        }
        else if(searchKind.equals("itemname")){
            List<Gifticon> gifticons = itemService.searchByItem(searchWhat);
            model.addAttribute("gifticons", gifticons);
        }
        return "search/search_result";
    }

각 경우에 따라 다른 함수를 호출한다.

search_result.html

<section style="margin-top: 40px;">
    <div th:if = "${!gifticons.isEmpty()}">
    <h2>
        ITEM LIST
    </h2>
    <table>
        <thead>
        <tr>
            <td>이름</td>
            <td>원가</td>
            <td>판매가</td>
            <td>할인율</td>
            <td>만료날짜</td>
            <td>업로드 날짜(최신 수정 날짜)</td>
        </tr>
        </thead>
        <tbody>
        <tr th:each="gifticon : ${gifticons}" th:onclick=#><!--기프티콘 상품 페이지로 이동-->
            <td th:text="${gifticon.name}">name</a></td>
            <td th:text="${gifticon.originalPrice}">originalPrice</td>
            <td th:text="${gifticon.sellingPrice}">sellingPrice</td>
            <td th:text="${gifticon.discountRate} + '%'">discountRate</td>
            <td th:text="${gifticon.expireDate}">expireDate</td>
            <td th:text="${gifticon.lastModifiedDate}">lastModifiedDate</td>
        </tr>
        </tbody>
    </table>
    </div>
    <h3 th:if = "${gifticons.isEmpty()}"> 찾으시는 항목이 존재하지 않습니다! </h3>
</section>

출력할 때, thymeleaf를 써서 리스트가 비어있으면, 찾으시는 항목이 존재하지 않는다고 띄워주었다.



'카테고리 - 음료'를 검색 했을 때, 결과는 위와 같고, 

아무것도 없으면 이렇게 뜬다! 

기쁘다.. 나도 무언가 했다. 다른 것도 하러간다

반응형

'코딩기록' 카테고리의 다른 글

인증용 테스트글  (0) 2023.09.03
마크다운 문서에서 체크박스를 쓰는 법  (0) 2022.06.04
profile

보글보글 개발일지

@보글

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!