Hibernate Reactive supports
Kotlin JDSL์ Hibernate Reactive๋ฅผ ์ฌ์ฉํ์ฌ ์ฟผ๋ฆฌ๋ฅผ ์ฝ๊ฒ ์คํํ ์ ์๋๋ก hibernate-reactive-support
๋ชจ๋์ ์ ๊ณตํฉ๋๋ค.
์ด ๋ชจ๋์ Hibernate Reactive์ Session
๋ฐ StatelessSession
๊ฐ์ฒด์ ๋ํ ํ์ฅ ํจ์๋ฅผ ์ ๊ณตํ์ฌ, Kotlin JDSL ์ฟผ๋ฆฌ ๊ฐ์ฒด๋ฅผ ์ง์ ์ ๋ฌํ์ฌ ๋ฆฌ์กํฐ๋ธ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์๊ฒ ํด์ค๋๋ค.
์ฟผ๋ฆฌ ์คํํ๊ธฐ
์ ๊ณต๋๋ ์ฃผ์ ํ์ฅ ํจ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
createQuery()
:Session
๊ณผStatelessSession
๋ชจ๋์์SELECT
๊ตฌ๋ฌธ์ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.StatelessSession
์ ๊ฒฝ์ฐ,UPDATE
์DELETE
๊ตฌ๋ฌธ์๋ ์ฌ์ฉ๋ฉ๋๋ค.createMutationQuery()
: ์ํ๋ฅผ ๊ฐ์ง๋(stateful)Session
์์UPDATE
์DELETE
๊ตฌ๋ฌธ์ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
์ด ํจ์๋ค์ ๋ณดํต SessionFactory
๋ก๋ถํฐ ์ป๋ Session
๋๋ StatelessSession
์ธ์คํด์ค์์ ์ฌ์ฉ๋ฉ๋๋ค.
Mutiny
Stateful Session (์ํ ๊ธฐ๋ฐ ์ธ์
)
์ํ๋ฅผ ๊ฐ์ง๋ Mutiny.Session
์์๋ SELECT
๊ตฌ๋ฌธ์ createQuery
๋ฅผ, UPDATE
/DELETE
๊ตฌ๋ฌธ์ createMutationQuery
๋ฅผ ์ฌ์ฉํฉ๋๋ค.
import com.linecorp.kotlinjdsl.support.hibernate.reactive.extension.createQuery
import com.linecorp.kotlinjdsl.support.hibernate.reactive.extension.createMutationQuery
import io.smallrye.mutiny.Uni
import org.hibernate.reactive.mutiny.Mutiny
val sessionFactory: Mutiny.SessionFactory = ...
val context = JpqlRenderContext()
// ๊ฒฐ๊ณผ ๋ชฉ๋ก ์กฐํ
val selectQuery = jpql {
select(
entity(Book::class)
).from(
entity(Book::class)
)
}
val books: Uni<List<Book>> = sessionFactory.withSession { session ->
session.createQuery(selectQuery, context).resultList
}
// Update ๊ตฌ๋ฌธ ์คํ
val updateQuery = jpql {
update(
entity(Book::class)
).set(
path(Book::price), BookPrice(10)
).where(
path(Book::isbn).eq(Isbn("01"))
)
}
val updatedRows: Uni<Int> = sessionFactory.withTransaction { session, _ ->
session.createMutationQuery(updateQuery, context).executeUpdate()
}
Stateless Session (์ํ ๋น์ ์ฅ ์ธ์
)
Mutiny.StatelessSession
์์๋ ๋ชจ๋ ์ข
๋ฅ์ ๊ตฌ๋ฌธ(SELECT
, UPDATE
, DELETE
)์ createQuery
ํ์ฅ ํจ์๊ฐ ์ฌ์ฉ๋ฉ๋๋ค.
import com.linecorp.kotlinjdsl.support.hibernate.reactive.extension.createQuery
// Stateless ์ธ์
์ผ๋ก delete ๊ตฌ๋ฌธ ์คํ
val deleteQuery = jpql {
deleteFrom(
entity(Book::class)
).where(
path(Book::isbn).eq(Isbn("01"))
)
}
val deletedRows: Uni<Int> = sessionFactory.withStatelessTransaction { session, _ ->
session.createQuery(deleteQuery, context).executeUpdate()
}
Stage
Stage.Session
๊ณผ Stage.StatelessSession
์ ์ฌ์ฉ ํจํด์ Mutiny์ ์ ์ฌํฉ๋๋ค.
Stateful Session (์ํ ๊ธฐ๋ฐ ์ธ์
)
import com.linecorp.kotlinjdsl.support.hibernate.reactive.extension.createQuery
import com.linecorp.kotlinjdsl.support.hibernate.reactive.extension.createMutationQuery
import java.util.concurrent.CompletionStage
import org.hibernate.reactive.stage.Stage
val sessionFactory: Stage.SessionFactory = ...
val context = JpqlRenderContext()
// ๊ฒฐ๊ณผ ๋ชฉ๋ก ์กฐํ
val selectQuery = jpql {
select(
entity(Book::class)
).from(
entity(Book::class)
)
}
val books: CompletionStage<List<Book>> = sessionFactory.withSession { session ->
session.createQuery(selectQuery, context).resultList
}
// Delete ๊ตฌ๋ฌธ ์คํ
val deleteQuery = jpql {
deleteFrom(
entity(Book::class)
).where(
path(Book::isbn).eq(Isbn("01"))
)
}
val deletedRows: CompletionStage<Int> = sessionFactory.withTransaction { session, _ ->
session.createMutationQuery(deleteQuery, context).executeUpdate()
}
Stateless Session (์ํ ๋น์ ์ฅ ์ธ์
)
import com.linecorp.kotlinjdsl.support.hibernate.reactive.extension.createQuery
// Stateless ์ธ์
์ผ๋ก delete ๊ตฌ๋ฌธ ์คํ
val deleteQuery = jpql {
deleteFrom(
entity(Book::class)
).where(
path(Book::isbn).eq(Isbn("01"))
)
}
val deletedRows: CompletionStage<Int> = sessionFactory.withStatelessTransaction { session, _ ->
session.createQuery(deleteQuery, context).executeUpdate()
}
Fetch ์ ๋ต๊ณผ ์ธ์
๋ฒ์์ ๋ํ ์ฐธ๊ณ ์ฌํญ
ํ์ฑํ๋ ๋ฆฌ์กํฐ๋ธ ์ธ์
์ธ๋ถ์์ ์ง์ฐ ๋ก๋ฉ๋ ์ฐ๊ด ๊ด๊ณ์ ์ ๊ทผํ๋ฉด LazyInitializationException
์ด ๋ฐ์ํฉ๋๋ค.
๋ฆฌ์กํฐ๋ธ ์ธ์
์ ๋ฒ์๋ ์ผ๋ฐ์ ์ผ๋ก withSession
์ด๋ withTransaction
๊ณผ ๊ฐ์ ๋ฉ์๋์ ๋๋ค ๋ธ๋ก์ผ๋ก ์ ํ๋ฉ๋๋ค. ๋ฆฌ์กํฐ๋ธ ์คํธ๋ฆผ์ด ์๋ฃ๋๊ณ ๋ธ๋ก ์คํ์ด ๋๋๋ฉด ์ธ์
์ ๋ซํ๋๋ค.
์์ ํ ๋ฐฉ๋ฒ: ์ธ์
๋ฒ์ ๋ด์์ ์ง์ฐ ๋ก๋ฉ๋ ์ฐ๊ด ๊ด๊ณ ์ ๊ทผํ๊ธฐ
์ธ์ ๋ฒ์ ๋ด์์ ์ ๊ทผํ๋ ํ, ์ง์ฐ ๋ก๋ฉ๋ ์ฐ๊ด ๊ด๊ณ๋ฅผ ์์ ํ๊ฒ ์ฌ์ฉํ ์ ์์ต๋๋ค.
val query = jpql {
select(
entity(Book::class)
).from(
entity(Book::class)
)
}
val bookAuthorSizes: Uni<List<Int>> = sessionFactory.withSession { session ->
session.createQuery(query, context).resultList.onItem().transform { bookList ->
// ์ธ์
์ด ์์ง ํ์ฑ ์ํ์ด๋ฏ๋ก ์ฌ๊ธฐ์ book.authors์ ์ ๊ทผํ๋ ๊ฒ์ ์์ ํฉ๋๋ค.
bookList.map { it.authors.size }
}
}
ํ์์ ์ธ ๋ฐฉ๋ฒ: ์ธ์
๋ฒ์ ๋ฐ์์ ์ฌ์ฉํ๊ธฐ ์ํด fetch join
์ฌ์ฉํ๊ธฐ
fetch join
์ฌ์ฉํ๊ธฐ์ธ์
์ด ๋ซํ ํ์ (์: ๋ฆฌ์กํฐ๋ธ ํ์ดํ๋ผ์ธ์ ๋ค์ ๋จ๊ณ์์) ์ฐ๊ด ๊ด๊ณ์ ์ ๊ทผํด์ผ ํ๋ ๊ฒฝ์ฐ, fetch join
์ ์ฌ์ฉํ์ฌ ๋ฐ๋์ ์ฆ์ ๋ก๋ฉํด์ผ ํฉ๋๋ค.
// fetch join์ ์ฌ์ฉํ์ฌ authors๋ฅผ ์ฆ์ ๋ก๋ฉํฉ๋๋ค.
val query = jpql {
select(
distinct(entity(Book::class))
).from(
entity(Book::class),
fetchJoin(Book::authors) // authors ์ปฌ๋ ์
์ ์ฆ์ fetchํฉ๋๋ค.
)
}
val books: Uni<List<Book>> = sessionFactory.withSession { session ->
session.createQuery(query, context).resultList
}
// authors ์ปฌ๋ ์
์ด ์ฆ์ ๋ก๋ฉ๋์์ผ๋ฏ๋ก ์ด์ ์์ ํฉ๋๋ค.
books.onItem().invoke { bookList ->
bookList.forEach { book ->
println(book.authors.size)
}
}
Last updated