· 오늘 공부한 것

전체조회할 때 querydsl으로 paging처리

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

최종 전에 진행했었던 프로젝트에서 경험해봤어야 했는데 하지 못하고 최종에서 구현하게 되었다. 페이징처리는 많은 곳에서 사용되기 때문에 무조건 알아두면 좋다고 생각한다. 무한스크롤이든지 게시글, 피드등 많은 정보들을 보여주는 곳에서 사용될 것이다. 그리고 지금까지 DB에서 데이터를 조회할 때 JPA에서 제공하는 query메서드만을 사용했었는데 이게 메서드명을 제대로 안하면 원하는 데이터를 얻지 못했다. 또한 메서드 명이 길어져서 한번에 파악하기 힘들다고 생각한다. 그래서 Query를 직접 만들어서 해당 메서드가 무슨 쿼리인지 보여줄 수는 있지만 이번에 좋은 기술은 querydsl를 적용하기로 하였다.

querydsl의 장점

  1. 타입 안정성(Type Safety):
    • QueryDSL은 컴파일 시간에 타입 검사를 제공합니다. 이는 오타나 잘못된 속성 사용으로 인한 런타임 오류를 방지하는 데 도움이 됩니다.
  2. 가독성 및 유지보수성:
    • QueryDSL은 자바 코드로 쿼리를 작성하므로 SQL 문자열을 사용하는 것보다 가독성이 뛰어나며, 자바 코드 자체가 좀 더 유지보수하기 쉽습니다. IDE의 지원을 받아 코드 자동 완성 및 리팩토링을 적용할 수 있습니다.
  3. 동적 쿼리 작성:
    • QueryDSL은 동적인 쿼리를 쉽게 작성할 수 있는 기능을 제공합니다. 조건에 따라서 동적으로 쿼리를 조립하거나 필요한 부분만 동적으로 추가하는 등의 작업이 가능합니다.
  4. 코드 재사용:
    • QueryDSL은 쿼리를 자바 코드로 작성하므로 코드를 메소드로 감싸거나 클래스로 추상화하여 재사용할 수 있습니다.
  5. ORM과의 통합:
    • QueryDSL은 주로 JPA, Hibernate, SQL, MongoDB 등의 ORM과 통합하여 사용할 수 있습니다. 특히 JPA와의 통합에서는 JPA 엔티티를 기반으로 쿼리를 작성할 수 있습니다.
  6. 컴파일러 체크와 IDE 지원:
    • QueryDSL은 쿼리를 컴파일 시간에 검사하므로 오타나 오류를 컴파일 전에 확인할 수 있습니다. 또한 대부분의 주요 IDE에서는 QueryDSL에 대한 풍부한 지원을 제공합니다.
  7. 풍부한 기능과 확장성:
    • QueryDSL은 다양한 기능을 지원하며, 복잡한 쿼리를 작성하는 데 필요한 많은 도구를 제공합니다. 특히 쿼리 조건, 정렬, 페이징, 서브쿼리 등을 다룰 수 있습니다.
  8. DSL 스타일 문법:
    • QueryDSL은 Domain Specific Language (DSL) 스타일의 문법을 제공하여 쿼리를 작성하기 쉽게 합니다. 직관적이고 자연스러운 문법을 사용하여 코드를 작성할 수 있습니다.

위와 같은 장점들이 있어서 인기있는 쿼리작성 도구이다. 하지만 처음 적용하는 거 부터 어려움을 겪었는데 3.x이상부터는 전보다 적용하는 방법이 간단해졌다. 

build.gradle

dependencies {
    // Querydsl 추가
	implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
	annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
	annotationProcessor "jakarta.annotation:jakarta.annotation-api"
	annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}

def querydslDir = "$buildDir/generated/querydsl"
sourceSets {
	main.java.srcDirs += querydslDir
}
tasks.withType(JavaCompile) {
	options.annotationProcessorGeneratedSourcesDirectory = file(querydslDir)
}

이후에 build를 하면 해당위치에 디렉토리가 생성되고 그 안에 작성한 entity들이 Q클래스로 자동생성된다. 즉 querydsl은 기존에 DB에 쿼리를 날리는 방식이 아닌 entity를 사용해서 쿼리문을 작성하게 된다. 작성방법은 기존 query문과 같아서 접근하는데 어렵지 않았다.

그런데 이 과정에서 아래와 같은 오류가 발생하였다.

List<Post> result =
                jpaQueryFactory
                        .selectFrom(QPost.post)
                        .leftJoin(QPost.post.postStacks, QPostStack.postStack)
                        .fetchJoin()
                        .leftJoin(QPost.post.jobLimits, QJobLimit.jobLimit)
                        .fetchJoin()
                        .where(skillEq(skill))
                        .offset(pageRequest.getOffset())
                        .limit(pageRequest.getPageSize())
                        .orderBy(QPost.post.createTimestamp.desc())
                        .fetch();

 

2024-01-17T17:10:26.972+09:00 ERROR 66037 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [com.spring.tming.domain.post.entity.Post.jobLimits, com.spring.tming.domain.post.entity.Post.postStacks]] with root cause

org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [com.spring.tming.domain.post.entity.Post

 

MultipleBagFetchException 오류는 Hibernate에서 여러 개의 Bag 타입의 컬렉션을 동시에 가져오려고 할 때 발생합니다. Bag은 Hibernate에서 컬렉션을 표현하는 기본적인 인터페이스 중 하나입니다.

이 오류를 해결하기 위해서는 한 엔터티에서 여러 Bag 타입의 컬렉션을 동시에 fetch join으로 가져오지 않아야 합니다. Bag은 순서가 있는 컬렉션으로, 동시에 여러 Bag를 가져오려고 하면 Hibernate가 어떤 컬렉션을 기준으로 정렬해야 하는지 알 수 없기 때문에 이러한 오류가 발생합니다.

 

그래서 순서의 보장이 필요없는 postStacks를 List가 아닌 Set으로 변경해서 해결하였다.

 

· 오늘 서칭 한 자료

https://jddng.tistory.com/345

 

Querydsl - Spring Data JPA에서 제공하는 페이징 활용

Spring Data JPA에서 제공하는 페이징 활용 QueryDSl에서 페이징 사용 Count 쿼리 최적화 Controller 개발 QueryDSL에서 페이징 사용 1. 커스텀 인터페이스에 메서드 추가 public interface MemberRepositoryCustom { List sea

jddng.tistory.com

 

 

· 느낀 점

- querydsl은 좋은 쿼리작성 도구이다. 직접 사용해보면서 느꼈다.

- 페이징처리.. 진작에 경험했어야 했는데 최종때 와서 막상 하려니 많이 헤맸다. (미리미리 해보자!)

- 기술면접을 꾸준히해야겠다. 알고리즘도...

반응형

+ Recent posts