본문 바로가기
Spring

querydsl 사용법!

by 리승우 2022. 10. 27.

querydsl 사용 깃 프로젝트 

 

https://github.com/SpartaPhotoGet/gloryoneteam.git

 

GitHub - SpartaPhotoGet/gloryoneteam: 백엔드

백엔드. Contribute to SpartaPhotoGet/gloryoneteam development by creating an account on GitHub.

github.com

 

 

1. build.gradle 환경 세팅

[참고사이트] https://velog.io/@jkijki12/Spring-QueryDSL-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0

 

2. gradle 내, other에서 compile.java 실행

=> 해당 작업으로 build -> generated -> querydsl 생성됨

 

3. 사용하고자하는 repository에 자신이 원하는 기능메서드를 추가한 customrepository 상속시킴

 

사용목적

>> 클라이언트 측에서 검색창에 임의의 값을 입력하였을 때 member에 해당하는 folder들 중, folder_name과 tag_name를 포함하는 값이 있을 시 해당하는 폴더들을 리스트 형식으로 반환하고자 함.

 

// 기존 폴더레포지토리에 커스텀 폴더레포지토리를 상속시켜준다
public interface FolderRepository extends JpaRepository<Folder, Long>, FolderRepositoryCustom {

    List<Folder> findAllByMemberOrderByDateDesc(Member member);

    List<Folder> findByMember(Member member);

}
// 커스텀 레포지토리에 메소드 쿼리문을 작성한다.
public interface FolderRepositoryCustom {
    List<Folder> findByKeyword(String keyword, Member member);
}

 

4. 클래스 파일 생성 후, 레포지토리 선언 + customrepository implements 실행 (JPA쿼리 의존성 주입도 실행)

그 후 원하는 로직작성

 

+조인하는 과정에서 쿼리성능 최적화하는 법 찾음!

아래에 주석으로 별도 추가해놓았음

// 폴더레포지토리커스텀을 해당 클래스에 implements한다. 그 후 해당 클래스를 @Repository로 주입하고 @RequriedArgsConstructor로 JPAQueryFactory를 주입한다. (사용하기 위해서)
@RequiredArgsConstructor
@Repository
public class FolderRepositoryImpl implements FolderRepositoryCustom {
    private final JPAQueryFactory queryFactory;


    // 여기서 커스텀 레포지토리에 적힌 것을 오버라이딩한다.
    @Override
    public List<Folder> findByKeyword(String keyword, Member member) {
        QFolder folder = QFolder.folder;
        QFolderTag folderTag = QFolderTag.folderTag;

        List<FolderTag> folderTagList = queryFactory.selectFrom(folderTag) // 폴터태그 모든 것을 리스트에 담는다.
                
                //쿼리성능 최적화
                .leftJoin(folderTag.folder,folder).on(folder.member.eq(member)) 해당코드로 교체 후 
                where절에 있는 .where(folder.member.eq(member)) 제거 시 쿼리성능이 더욱 높아짐
                
                //추가로, or절을 활용하여 search메소드를 안 써도 되는 방법은 아래와 같다.
                        .where(folder.folderName.contains(keyword)
                        .or(folderTag.tagName.contains(keyword))
                )
                
                
                .leftJoin(folderTag.folder,folder).fetchJoin() // 폴더테그의 폴더와 폴더를 leftjoin으로 연걸한다.
                // fetchJoin을 활용해서 N+1문제를 해결할 수 있다. 폴더태그와 폴더를 함께 조회해서 지연로딩을 X로 만든다.
                .where(folder.member.eq(member)) //본인 쓴 폴더만 조회 (Q폴더가 매개변수 멤버와 동일한지 조건문)
                .where(search(keyword)) //파일이름 or 태그 검색 / search메소드 동작
                .orderBy(folder.date.desc()) // 날짜 내림차순 정렬
                .fetch(); // 기존에 조인된 것을 다시 해제

        return folderTagList.stream()
                .map(FolderTag::getFolder)
                .distinct() // 중복제거
                .collect(Collectors.toList());
    }

    private BooleanBuilder search(String keyword){
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        if(hasText(keyword)){
            booleanBuilder.or(folder.folderName.contains(keyword));
        }
        if(hasText(keyword)){
            booleanBuilder.or(folderTag.tagName.contains(keyword));
        }
        return booleanBuilder;
    }
}

 

5. 위 로직을 사용하길 희망하는 곳에서 사용하면 됨

@Service
@RequiredArgsConstructor
public class SearchFolderService {

    private final FolderRepository folderRepository;

    @Transactional(readOnly = true)
    public List<FolderSearchResDto> searchTagFolder(String query, Member member) {

        // 아래 코드에서 작성된 메서드 호출 후 실행
        List<Folder> folders = folderRepository.findByKeyword(query, member);

        return folders.stream().map(FolderSearchResDto::new).collect(Collectors.toList());
    }

}

 

'Spring' 카테고리의 다른 글

ExceptionHandler / ControllerAdvice 사용법  (0) 2022.11.03
WebSocket / STOMP  (1) 2022.10.28
Spring. Filter/Interceptor  (0) 2022.10.13
Spring. 영속성이란 (persistence)  (0) 2022.10.13
Spring. JPA ORM 및 연관관계  (0) 2022.10.13

댓글