✅ 검색 기능 구현

Yuri Lee·2020년 12월 9일
0

GET “/search/study”

  • keyword 입력 받아서 스터디 검색
  • 스터디 제목, 태그 이름, 도시 로컬 이름에 해당하는 키워드를 가지고 있는 공개된 스터디

메서드로 안하고 Querydsl 사용! 이번에는 확장 구현체를 만드는 방법을 사용해 볼 것

public class StudyRepositoryExtensionImpl extends QuerydslRepositorySupport implements StudyRepositoryExtension

StudyRepositoryExtensionImpl 에서 Extension 부분은 마음대로 설정해도 되지만, 이 인터페이스를 구현한 구현체를 만들 때는 반드시 Impl 을 붙여줘야 한다.

Querydsl 로 구현을 할 것인데, 이때 사용할 수 있는 도우미 클래스로 QuerydslRepositorySupport 가 있다. 이때 컴파일 에러가 발생한다! 😱😱

Q. 왜?

  • 이 Repository 에 어떤 인스턴스를 만들려고 하면 상위 클래스의 생성자도 호출한다. (기본 생성자밖에 없으므로)
    public StudyRepositoryExtensionImpl() {
        super(Study.class);
    }

Q. 생성자를 만들어주면 해결, 왜 생성자를 만들어줬을까?

  • 여기서 상위 클래스의 기본 생성자가 없다. 그래서 컴파일 에러가 난 것이고 그래서 다음과 같이 생성자를 만들어준 것이다. 우리는 어떤 도메인을 다루는 repository인지 알고 있으므로 다른 곳에서 받아올 필요 없이 Study.class를 넘겨주면 된다.
  • repository는 @Transactional(readOnly = true) 기본은 readOnly
  • service는 @Transactional 붙이고 readOnly 없이

조회는 주로 repository 통해서 하기로 함! 이제 본격적으로 Querydsl 를 사용하면 되는데 이전 처럼 Predicate 를 사용하지 않고, from 으로 시작할 수 있다.

조회

  • 페이징 없이
  • 정렬 조건 없이
  • 로그인 없이도 사용 가능

보여줄 내용

  • 검색 키워드와 결과 개수, 없으면 없다고 표기
  • 스터디 당 보여줄 정보
    • 스터디 이름
    • 짧은 소개
    • 태그
    • 지역
    • 멤버 수
    • 스터디 공개 일시

비어있는 lists라서 사이즈로 비교하면 가능했는데, 왜 안되는지 ...? -> 이해할 수 없는 상황
타임리프가 제공하는 lists 라는 기능이 있다. #lists.isEmpty(studyList)

참고

    select
        study0_.id as id1_7_,
        study0_.closed as closed2_7_,
        study0_.closed_date_time as closed_d3_7_,
        study0_.full_description as full_des4_7_,
        study0_.image as image5_7_,
        study0_.path as path6_7_,
        study0_.published as publishe7_7_,
        study0_.published_date_time as publishe8_7_,
        study0_.recruiting as recruiti9_7_,
        study0_.recruiting_updated_date_time as recruit10_7_,
        study0_.short_description as short_d11_7_,
        study0_.title as title12_7_,
        study0_.use_banner as use_ban13_7_ 
    from
        study study0_ 
    where
        study0_.published=? 
        and (
            lower(study0_.title) like ? escape '!'
        ) 
        or exists (
            select
                1 
            from
                study_tags tags1_,
                tag tag2_ 
            where
                study0_.id=tags1_.study_id 
                and tags1_.tags_id=tag2_.id 
                and (
                    lower(tag2_.title) like ? escape '!'
                )
        ) 
        or exists (
            select
                1 
            from
                study_zones zones3_,
                zone zone4_ 
            where
                study0_.id=zones3_.study_id 
                and zones3_.zones_id=zone4_.id 
                and (
                    lower(zone4_.local_name_of_city) like ? escape '!'
                )
        )

db 에다가 실행해 볼 수 있다. 그대로!

n+1 select 문제 발생

검색 창에 jpa를 검색했다고 하자. 이때 나오는 스터디 개수를 3개라고 했을 때 스터디 한번 조회하고, 스터디 당 태그, 존, 멤버/ 태그 존, 멤버/ 태그 존, 멤버가 3개씩 발생한다. 이는 n+1 select 문제이다. 여태까지는 이를 해결하기 위해 엔티티 그래프를 사용했다. 하지만 지금 Querydsl 을 사용하고 있으므로 패치할 내용도 쿼리해서 사용해야 한다.


출처 : 인프런 백기선님의 스프링과 JPA 기반 웹 애플리케이션 개발

profile
Step by step goes a long way ✨

0개의 댓글