diff --git a/docs/en/jpql-with-kotlin-jdsl/statements.md b/docs/en/jpql-with-kotlin-jdsl/statements.md index 184a8eb1b..82db62d29 100644 --- a/docs/en/jpql-with-kotlin-jdsl/statements.md +++ b/docs/en/jpql-with-kotlin-jdsl/statements.md @@ -126,6 +126,77 @@ from( ) ``` +### Select From clause + +Use `selectFrom()` and pass [Entity](entities.md) and [Join](statements.md#Join-For-SelectFrom) to specify the entities for selection. +In the `selectFrom()` function you can create the select and from clause at once. +'SelectFrom()' has the same effect as calling the existing 'select()' and 'from()', respectively. + +```kotlin +// selectFrom stmt +selectFrom(entity(Author::class)) + +// select and from stms +select( + entity(Author::class) +).from( + entity(Employee::class) +) +``` + +#### Join For SelectFrom + +It is the same as [Join](statements.md#Join) above. + +```kotlin +@Entity +// ... +class Book( + // ... + + @OneToMany(mappedBy = "book", cascade = [CascadeType.ALL], orphanRemoval = true) + val authors: MutableSet, +) + +@Entity +// ... +class BookAuthor( + @Id + @Column(name = "author_id") + val authorId: Long, +) { + @Id + @ManyToOne + @JoinColumn(name = "isbn") + lateinit var book: Book +} + +@Entity +// ... +class Author( + @Id + @Column(name = "author_id") + val authorId: Long, + + // ... +) + +selectFrom( + entity(Book::class), + join(Book::authors), // Association Join + join(Author::class).on(path(BookAuthor::authorId).eq(path(Author::authorId))), // Join +) +``` + +Calling 'as()' after 'join()' can also achieve the same result as [Join](statements.md#Join) + +```kotlin +selectFrom( + entity(Book::class), + join(Book::authors).`as`(entity(BookAuthor::class, "author")), +) +``` + ### Where clause Use `where()` and pass [Predicate](predicates.md) to restrict the data when building a where clause in the select statement. diff --git a/docs/ko/jpql-with-kotlin-jdsl/statements.md b/docs/ko/jpql-with-kotlin-jdsl/statements.md index 74bf397bc..6b69e9ef0 100644 --- a/docs/ko/jpql-with-kotlin-jdsl/statements.md +++ b/docs/ko/jpql-with-kotlin-jdsl/statements.md @@ -128,6 +128,77 @@ from( ) ``` +### Select From clause + +select statement의 select clause와 from clause를 한 번에 만들기 위해, `selectFrom()`을 이용할 수 있습니다. +`selectFrom()`은 [Entity](entities.md)와 [Join](statements.md#Join-For-SelectFrom)을 파라미터로 받아 어떤 entity를 통해 조회가 되는지 표현합니다. +`selectFrom()`은 기존의 `select()`, `from()`을 각각 호출하는 것과 동일한 효과를 가져옵니다. + +```kotlin +// selectFrom stmt +selectFrom(entity(Author::class)) + +// select and from stms +select( + entity(Author::class) +).from( + entity(Employee::class) +) +``` + +#### Join For SelectFrom + +위의 [Join](statements.md#Join)과 동일한 역할을 합니다. + +```kotlin +@Entity +// ... +class Book( + // ... + + @OneToMany(mappedBy = "book", cascade = [CascadeType.ALL], orphanRemoval = true) + val authors: MutableSet, +) + +@Entity +// ... +class BookAuthor( + @Id + @Column(name = "author_id") + val authorId: Long, +) { + @Id + @ManyToOne + @JoinColumn(name = "isbn") + lateinit var book: Book +} + +@Entity +// ... +class Author( + @Id + @Column(name = "author_id") + val authorId: Long, + + // ... +) + +selectFrom( + entity(Book::class), + join(Book::authors), // Association Join + join(Author::class).on(path(BookAuthor::authorId).eq(path(Author::authorId))), // Join +) +``` + +`join()` 이후에 `as()`를 호출하 것 또한 [Join](statements.md#Join)와 동일한 결과를 얻을 수 있습니다. + +```kotlin +selectFrom( + entity(Book::class), + join(Book::authors).`as`(entity(BookAuthor::class, "author")), +) +``` + ### Where clause select statement의 where clause를 만들기 위해, `where()`를 사용할 수 있습니다. diff --git a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt index 13d54c210..46952d343 100644 --- a/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt +++ b/dsl/jpql/src/main/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/Jpql.kt @@ -19,6 +19,7 @@ import com.linecorp.kotlinjdsl.dsl.jpql.join.impl.AssociationJoinDsl import com.linecorp.kotlinjdsl.dsl.jpql.join.impl.FetchJoinDsl import com.linecorp.kotlinjdsl.dsl.jpql.join.impl.JoinDsl import com.linecorp.kotlinjdsl.dsl.jpql.select.SelectQueryFromStep +import com.linecorp.kotlinjdsl.dsl.jpql.select.SelectQueryWhereStep import com.linecorp.kotlinjdsl.dsl.jpql.select.impl.SelectQueryFromStepDsl import com.linecorp.kotlinjdsl.dsl.jpql.sort.SortNullsStep import com.linecorp.kotlinjdsl.dsl.jpql.sort.impl.SortDsl @@ -33,6 +34,7 @@ import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expression import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expressionable import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Expressions import com.linecorp.kotlinjdsl.querymodel.jpql.expression.Subquery +import com.linecorp.kotlinjdsl.querymodel.jpql.from.Fromable import com.linecorp.kotlinjdsl.querymodel.jpql.join.JoinType import com.linecorp.kotlinjdsl.querymodel.jpql.path.Path import com.linecorp.kotlinjdsl.querymodel.jpql.path.Pathable @@ -3119,6 +3121,18 @@ open class Jpql : JpqlDsl { ) } + /** + * Creates a select clause in a select from query. + */ + @SinceJdsl("3.5.3") + inline fun selectFrom( + expr: Entityable, + vararg froms: Fromable?, + ): SelectQueryWhereStep { + return select(expr) + .from(expr, *froms) + } + /** * Creates a select clause in a select query. */ diff --git a/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/select/FromDslTest.kt b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/select/FromDslTest.kt index 24cc2f7ef..0311d5f84 100644 --- a/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/select/FromDslTest.kt +++ b/dsl/jpql/src/test/kotlin/com/linecorp/kotlinjdsl/dsl/jpql/select/FromDslTest.kt @@ -88,4 +88,59 @@ class FromDslTest : WithAssertions { assertThat(actual).isEqualTo(expected) } + + @Test + fun `selectFrom() with entity`() { + // when + val selectFrom = queryPart { + selectFrom( + entity1, + ) + }.toQuery() + val actual: SelectQuery = selectFrom + + // then + val expected = SelectQueries.selectQuery( + returnType = Book::class, + distinct = false, + select = listOf(entity1), + from = listOf( + entity1, + ), + ) + + assertThat(actual).isEqualTo(expected) + } + + @Test + fun `selectFrom() with froms`() { + // when + val selectFrom = queryPart { + selectFrom( + entity1, + null, + entity2, + null, + join1, + null, + join2, + ) + }.toQuery() + val actual: SelectQuery = selectFrom + + // then + val expected = SelectQueries.selectQuery( + returnType = Book::class, + distinct = false, + select = listOf(entity1), + from = listOf( + entity1, + entity2, + join1, + join2, + ), + ) + + assertThat(actual).isEqualTo(expected) + } } diff --git a/example/eclipselink-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/eclipselink/javax/select/SelectExample.kt b/example/eclipselink-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/eclipselink/javax/select/SelectExample.kt index 67940ee69..f0e09dc82 100644 --- a/example/eclipselink-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/eclipselink/javax/select/SelectExample.kt +++ b/example/eclipselink-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/eclipselink/javax/select/SelectExample.kt @@ -70,6 +70,26 @@ class SelectExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = entityManager.createQuery(query, context).resultList + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the book with the most authors`() { // when diff --git a/example/eclipselink/src/test/kotlin/com/linecorp/kotlinjdsl/example/eclipselink/select/SelectExample.kt b/example/eclipselink/src/test/kotlin/com/linecorp/kotlinjdsl/example/eclipselink/select/SelectExample.kt index aa315dd1f..ccf482195 100644 --- a/example/eclipselink/src/test/kotlin/com/linecorp/kotlinjdsl/example/eclipselink/select/SelectExample.kt +++ b/example/eclipselink/src/test/kotlin/com/linecorp/kotlinjdsl/example/eclipselink/select/SelectExample.kt @@ -70,6 +70,26 @@ class SelectExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = entityManager.createQuery(query, context).resultList + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the book with the most authors`() { // when diff --git a/example/hibernate-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/jpql/hibernate/javax/select/SelectExample.kt b/example/hibernate-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/jpql/hibernate/javax/select/SelectExample.kt index d0d77e2c2..7abbfe216 100644 --- a/example/hibernate-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/jpql/hibernate/javax/select/SelectExample.kt +++ b/example/hibernate-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/jpql/hibernate/javax/select/SelectExample.kt @@ -71,6 +71,26 @@ class SelectExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = entityManager.createQuery(query, context).resultList + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun books() { // when diff --git a/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectMutinySessionExample.kt b/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectMutinySessionExample.kt index 01e67d41c..46981657d 100644 --- a/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectMutinySessionExample.kt +++ b/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectMutinySessionExample.kt @@ -68,6 +68,28 @@ class SelectMutinySessionExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = sessionFactory.withSession { + it.createQuery(query, context).resultList + }.await().indefinitely() + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the book with the most authors`() { // when diff --git a/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectMutinyStatelessSessionExample.kt b/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectMutinyStatelessSessionExample.kt index da36608e2..29aecd070 100644 --- a/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectMutinyStatelessSessionExample.kt +++ b/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectMutinyStatelessSessionExample.kt @@ -68,6 +68,28 @@ class SelectMutinyStatelessSessionExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = sessionFactory.withStatelessSession { + it.createQuery(query, context).resultList + }.await().indefinitely() + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the book with the most authors`() { // when diff --git a/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectStageSessionExample.kt b/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectStageSessionExample.kt index 22c2ed12c..bd5996f37 100644 --- a/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectStageSessionExample.kt +++ b/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectStageSessionExample.kt @@ -68,6 +68,28 @@ class SelectStageSessionExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = sessionFactory.withSession { + it.createQuery(query, context).resultList + }.toCompletableFuture().get() + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the book with the most authors`() { // when diff --git a/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectStageStatelessSessionExample.kt b/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectStageStatelessSessionExample.kt index 6fc85aec5..e3094c724 100644 --- a/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectStageStatelessSessionExample.kt +++ b/example/hibernate-reactive-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/javax/jpql/select/SelectStageStatelessSessionExample.kt @@ -68,6 +68,28 @@ class SelectStageStatelessSessionExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = sessionFactory.withStatelessSession { + it.createQuery(query, context).resultList + }.toCompletableFuture().get() + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the book with the most authors`() { // when diff --git a/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectMutinySessionExample.kt b/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectMutinySessionExample.kt index 96c066ac4..bb1cdf345 100644 --- a/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectMutinySessionExample.kt +++ b/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectMutinySessionExample.kt @@ -68,6 +68,28 @@ class SelectMutinySessionExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = sessionFactory.withSession { + it.createQuery(query, context).resultList + }.await().indefinitely() + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the book with the most authors`() { // when diff --git a/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectMutinyStatelessSessionExample.kt b/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectMutinyStatelessSessionExample.kt index 6e5f1dae9..ce6afcc54 100644 --- a/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectMutinyStatelessSessionExample.kt +++ b/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectMutinyStatelessSessionExample.kt @@ -68,6 +68,28 @@ class SelectMutinyStatelessSessionExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = sessionFactory.withStatelessSession { + it.createQuery(query, context).resultList + }.await().indefinitely() + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the book with the most authors`() { // when diff --git a/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectStageSessionExample.kt b/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectStageSessionExample.kt index 03517e035..cc80dda90 100644 --- a/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectStageSessionExample.kt +++ b/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectStageSessionExample.kt @@ -68,6 +68,28 @@ class SelectStageSessionExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = sessionFactory.withSession { + it.createQuery(query, context).resultList + }.toCompletableFuture().get() + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the book with the most authors`() { // when diff --git a/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectStageStatelessSessionExample.kt b/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectStageStatelessSessionExample.kt index 1e62e2511..1f6236d84 100644 --- a/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectStageStatelessSessionExample.kt +++ b/example/hibernate-reactive/src/test/kotlin/com/linecorp/kotlinjdsl/example/hibernate/reactive/jakarta/jpql/select/SelectStageStatelessSessionExample.kt @@ -68,6 +68,28 @@ class SelectStageStatelessSessionExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = sessionFactory.withStatelessSession { + it.createQuery(query, context).resultList + }.toCompletableFuture().get() + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the book with the most authors`() { // when diff --git a/example/hibernate/src/test/kotlin/com/linecorp/kotlinjdsl/example/jpql/hibernate/select/SelectExample.kt b/example/hibernate/src/test/kotlin/com/linecorp/kotlinjdsl/example/jpql/hibernate/select/SelectExample.kt index 91b557cab..c84780a00 100644 --- a/example/hibernate/src/test/kotlin/com/linecorp/kotlinjdsl/example/jpql/hibernate/select/SelectExample.kt +++ b/example/hibernate/src/test/kotlin/com/linecorp/kotlinjdsl/example/jpql/hibernate/select/SelectExample.kt @@ -71,6 +71,26 @@ class SelectExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val query = jpql { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + val actual = entityManager.createQuery(query, context).resultList + + // then + assertThat(actual.map { it.authorId }).isEqualTo(listOf(4L)) + } + @Test fun books() { // when diff --git a/example/spring-data-jpa-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/spring/data/jpa/javax/jpql/select/SelectExample.kt b/example/spring-data-jpa-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/spring/data/jpa/javax/jpql/select/SelectExample.kt index 5f30e16c0..0cb5e4cdb 100644 --- a/example/spring-data-jpa-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/spring/data/jpa/javax/jpql/select/SelectExample.kt +++ b/example/spring-data-jpa-javax/src/test/kotlin/com/linecorp/kotlinjdsl/example/spring/data/jpa/javax/jpql/select/SelectExample.kt @@ -71,6 +71,24 @@ class SelectExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val actual = authorRepository.findAll { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + // then + assertThat(actual.map { it?.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the list of books`() { // given diff --git a/example/spring-data-jpa/src/test/kotlin/com/linecorp/kotlinjdsl/example/spring/data/jpa/jpql/select/SelectExample.kt b/example/spring-data-jpa/src/test/kotlin/com/linecorp/kotlinjdsl/example/spring/data/jpa/jpql/select/SelectExample.kt index aaa6de0ed..e58da2b25 100644 --- a/example/spring-data-jpa/src/test/kotlin/com/linecorp/kotlinjdsl/example/spring/data/jpa/jpql/select/SelectExample.kt +++ b/example/spring-data-jpa/src/test/kotlin/com/linecorp/kotlinjdsl/example/spring/data/jpa/jpql/select/SelectExample.kt @@ -90,6 +90,24 @@ class SelectExample : WithAssertions { assertThat(actual).isEqualTo(listOf(4L)) } + @Test + fun `authors who haven't written a book with selectFrom`() { + // when + val actual = authorRepository.findAll { + selectFrom( + entity(Author::class), + leftJoin(BookAuthor::class).on(path(Author::authorId).equal(path(BookAuthor::authorId))), + ).where( + path(BookAuthor::authorId).isNull(), + ).orderBy( + path(Author::authorId).asc(), + ) + } + + // then + assertThat(actual.map { it?.authorId }).isEqualTo(listOf(4L)) + } + @Test fun `the list of books`() { // given