DTO Projection 과 JPQL

devswansong·2024년 9월 13일

본래 Hibernate 에서 생성해주는 쿼리 메소드만 사용해본터라 DTO Projection , JPQL 이 정확히 뭔지 모른채 살아왔습니다.

이번에 Kotlin Jdsl 이란 쿼리 빌더 기술을 사용하게 되면서 평소의 부족한 지식을 채우고자 글을 적습니다.

DTO Projection

Entity 에서 특정 필드를 선택해 Custom class 또는 Data class에 직접 매핑할 수 있는 방식입니다.

즉, 모든 필드가 필요하진 않고 특정 필드만 필요할 시 사용하면 유용할 수 있습니다.

data class AuthorDto(val id: Long, val name: String)

val authors = queryFactory.listQuery<AuthorDto> {
    select(
        path(Author::id),
        path(Author::name)
    )
    from(entity(Author::class))
}

JPQL (Java Persistence Query Language)

DB 에 특정되지 않는 객체지향형 쿼리 언어이며 이는 JPA 스펙의 일부입니다.
단순한 언어이며 이를 이용해 Type-safe 같은 장점을 얻을 수 있습니다.

아래 예시를 보면 알 수 있듯

// JPQL

SELECT a.authorId 
FROM Author a 
JOIN BookAuthor ba ON a.authorId = ba.authorId 
GROUP BY a.authorId 
ORDER BY COUNT(a.authorId) DESC
// Kotlin JDSL 로 작성한 JPQL

val query = jpql {
    select(
        path(Author::authorId),
    ).from(
        entity(Author::class),
        join(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))),
    ).groupBy(
        path(Author::authorId),
    ).orderBy(
        count(Author::authorId).desc(),
    )
}
  • JPQL vs SQL
  1. 객체지향 vs 테이블지향
    • JPQL 은 객체지향적이며 Entity 객체와 그 Properties 로 동작합니다.
    • SQL 은 테이블지향적이며 DB 테이블과 Column 으로 동작합니다.
  2. DB 의존 여부
    • JPQL 은 DB 비의존적이며 DB 의 변화에 영향을 받지 않습니다.
    • SQL 은 DB 에 따라 문법이 조금씩 다를 수 있습니다.
  3. 추상화 수준
    • JPQL 은 자바 객체로 다뤄지며 높은 추상화 수준을 가집니다.
    • SQL 은 DB 에 직접적으로 작용합니다.
  4. Entity 매핑
    • JPQL 쿼리는 Entity 클래스와 Field 이름으로 작성됩니다. (객체지향적)
    • SQL 쿼리는 테이블, Column 이름으로 작성됩니다.
  5. 이식성
    • DB 의존 여부에 따라 이식성의 난이도가 다릅니다. (의존 낮을 수록 이식성 높아짐)
  6. 기능
    • JPQL 은 객체지향 컨셉을 따르며 상속과 다형성을 지원합니다.
    • SQL 은 복잡한 데이터들을 조작하고 분석하는데 더 많은 기능을 제공합니다.
      (JPQL 의 추상화가 모든 DB 의 기능을 일반화하진 못하는 듯 합니다.)
  7. 성능
    • JPQL 은 가끔씩 직접 작성한 SQL 쿼리보다 최적화가 별로일 수 있습니다.
    • SQL 은 성능 좋은 최적화 기능을 가지고 있습니다.
  8. 러닝 커브
    • JPQL 은 자바 개발자들이 배우고 쓰기 쉽습니다.
    • SQL 은 특정 DB 마다 문법이나 세부 지식들을 배워야 합니다.
  9. 서브쿼리 지원 여부
    • JPQL 은 서브쿼리 사용에 제한이 있습니다.
      (FROM 절에서 사용이 힘듭니다.
      JPA 는 WHERE, HAVING 절에서 서브쿼리가 가능하며 Hibernate 은 SELECT 절에서도 가능하게 합니다.
      하지만 FROM 절에선 사용이 불가능하니 목적이 분명하다면 네이티브 쿼리를 사용해야 합니다.
      그래도 FROM 절은 JOIN 으로 해결할 가능성이 있으니 JOIN 을 사용하던가 쿼리를 두 번 날리는 것도 좋다 합니다.)
    • SQL 은 큰 제한이 없습니다.
  10. JPA 와의 통합
    • JPQL 은 JPA 에 적합하게 설계되었습니다.
    • SQL 은 네이티브 쿼리를 통해 JPA 와 사용되어질 수 있지만 ORM 컨셉에서 완전히 통합되긴 힘듭니다. (지향하는 바가 다르니..)

정리

정의를 보면 알 수 있는데 둘은 상반된 개념이 아닙니다. DTO Projection 은 쿼리 결과 매핑 방식이고 JQPL 은 SQL 을 추상화한 개념으로 볼 수 있습니다.

Kotlin Jdsl 을 공부하다 생각나 쓴 글이니 이와 관련된 한 마디로 정리하고 끝내겠습니다.

Kotlin Jdsl 을 가지고 Type-safe 하게 JPQL 을 작성할 수 있습니다! 왜 JPQL 이냐하면 DB 마다 다를 수 있는 SQL 대신 추상화된 쿼리 언어이기 때문인 것 같습니다!
(꼭 JPQL 만 만드는 건 아닌것 같습니다. 이후 공부하게 된다면 또 정리하겠습니다.)

참고한 글

https://kotlin-jdsl.gitbook.io/docs/v/ko-1/faq/how-do-i-use-kotlin-value-class
https://stackoverflow.com/questions/54848250/what-should-i-prefer-using-jpa-pure-sql-or-jpql-and-how-to-create-delete-table
https://ittrue.tistory.com/270
https://sun-22.tistory.com/78

profile
unagi.zoso == ziggy stardust == devswansong

0개의 댓글