-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Documentation of why Kotlin JDSL returns a nullable list in the Spring Support module. #685
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Why does Kotlin JDSL allow nullable return types? | ||
|
||
Kotlin JDSL helps developers develop more efficiently by allowing them to write queries without creating a separate metadata model or making string syntax errors. | ||
However, Kotlin JDSL users may sometimes have questions about nullable return types in the form of Slice<T?> or Page<T?> returned when calling APIs like findSlice or findPage methods. | ||
|
||
## Why do we need nullable return types? | ||
|
||
The reason why Kotlin JDSL supports nullable return types is that depending on how the JPQL query is written, some of the returned list items may contain null values. | ||
The simplest example is when you look up a column or entity without using DTO Projection. | ||
|
||
The table below shows some of the cases where nullable return types can occur when using the Kotlin JDSL. | ||
|
||
| Item | Nullable or not | Reason | | ||
|----------------|-----------------|------------------------------------------------------------------------------------------------------| | ||
| DTO Projection | X | Calling the constructor for all ROWs results in the object being created, which does not allow nulls | | ||
| Column | O | Exists when looking up a field that is null | | ||
| Entity | O | Exists if the Entity being joined on Left Join is null. | | ||
|
||
As another example, the code below shows a situation where the Author entity exists, but the BookAuthor entity, the target of the left join, may be null. | ||
|
||
```kotlin | ||
val query = jpql { | ||
select( | ||
path(BookAuthor), | ||
cj848 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
).from( | ||
entity(Author::class), | ||
leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), | ||
) | ||
} | ||
``` | ||
|
||
## Background on the design decision | ||
|
||
In the early development of Kotlin JDSL 3.0, we tried nullable inference. | ||
This was an attempt to automatically infer whether a query result is nullable through the type system. | ||
However, during the development of queries that use JOIN, we encountered the problem that perfect nullable inference was not possible. | ||
|
||
Starting with Kotlin JDSL 3.0, we're settling on a path that utilizes the user's query writing knowledge as much as possible, with a small learning curve. | ||
This avoids confusion due to different interfaces for different users, and allows them to build on their existing JPQL knowledge without having to learn Kotlin JDSL syntax separately. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# 왜 Kotlin JDSL은 nullable한 반환 타입을 허용하나요? | ||
|
||
Kotlin JDSL을 사용하면 별도의 메타데이터 모델 생성이나 문자열 문법 오류 없이 쿼리를 작성할 수 있도록 도와주어 개발자가 보다 효율적으로 개발할 수 있게 도와줍니다. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 메타데이터 모델 생성은 nullable 주제와는 연관이 적어 보입니다. 'Type Safe하게 쿼리를 작성할 수 있게 도와주지만, 왜 리스트 반환 시에는 non-null한 것도 nullable하게 반환하는지 궁금하실 수 있다' 는 스토리로 글을 풀어가면 좋을 것 같습니다. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 음 확실히 저번에 올린 PR(메타 모델)과는 성격이 다른 것 같아요. 수정하겠습니다! |
||
그러나 Kotlin JDSL 사용자는 때때로 findSlice나 findPage 메소드 같은 API 호출 시 반환되는 Slice<T?> 또는 Page<T?> 형태의 nullable 반환 타입에 대해 궁금증을 가질 수 있습니다. | ||
|
||
## Nullable 반환 타입의 필요성 | ||
|
||
Kotlin JDSL이 nullable한 반환 타입을 지원하는 이유는 JPQL 쿼리의 작성 방법에 따라 반환되는 리스트 항목 중 null 값이 포함될 수 있기 때문입니다. | ||
가장 간단한 예로는 DTO Projection을 사용하지 않고, column이나 entity를 조회할 때를 들 수 있습니다. | ||
|
||
아래 표는 Kotlin JDSL을 사용할 때 nullable한 반환 타입이 발생할 수 있는 몇 가지 경우를 나타냅니다. | ||
|
||
| 항목 | null 여부 | 이유 | | ||
|----------------|---------|---------------------------------------------------------| | ||
| DTO Projection | X | 모든 ROW에 대한 생성자 호출하기 때문에 객체가 생성되어 null을 허용하는 결과가 나오지 않음 | | ||
| Column | O | null인 필드를 조회하는 경우 존재 | | ||
| Entity | O | Left Join시 조인의 대상이 되는 Entity가 null인 경우 존재 | | ||
|
||
또 다른 예로 아래 코드는 Author 엔티티가 있지만, left join의 대상인 BookAuthor 엔티티는 null일 수 있는 상황을 보여줍니다. | ||
|
||
```kotlin | ||
val query = jpql { | ||
select( | ||
path(BookAuthor), | ||
cj848 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
).from( | ||
entity(Author::class), | ||
leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), | ||
) | ||
} | ||
``` | ||
|
||
## 설계 결정의 배경 | ||
|
||
초기 Kotlin JDSL 3.0 개발 시에는 nullable 추론을 시도했습니다. | ||
이는 쿼리 결과의 nullable 여부를 타입 시스템을 통해 자동으로 추론하려는 시도였습니다. | ||
하지만, join을 사용하는 쿼리의 개발 과정에서 완벽한 nullable 추론이 불가능하다는 문제에 직면했습니다. | ||
|
||
Kotlin JDSL 3.0부터는 되도록 사용자가 알고 있는 쿼리 작성 지식만을 활용해서 적은 러닝 커브로 사용할 수 있게 하는 노선으로 정착합니다. | ||
이는 사용자가 바라보는 인터페이스가 각자 달라 혼란을 방지하고, Kotlin JDSL 문법을 별도로 학습할 필요 없이 기존의 JPQL 지식을 기반으로 활용할 수 있게 합니다. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is inaccurate information. In case of DTO Projection, Nullable is also allowed. For example
When there is an entity like the above, null may occur at the time of the query below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is correct information. When using the new keyword in JPQL, the constructor is called for every row to create the object. That's why there can't be a nullable for DTO Projection only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you mean returning a DTO object itself, that is correct.
I meant that the fields in the object are nullable, but that seems to be incorrect information. Thanks for the good point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see you got it, I'll add it to the documentation!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's nice to be able to check it with test code.