Reputation: 313
Here is a simple example of @OneToOne
entity mapping using Java 11, Spring Boot 2.4.5 and Hibernate 5.4.29.
In Java implementation Lazy loading works fine - only Post
entity is loaded:
select id, details_id from post
Here is the same code in Kotlin. It produces following SQL:
select id, details_id from post
select pd.id, p.id, p.details_id
from post_details pd
left outer join post p on pd.id = p.details_id
where pd.id = ?
select p.id, p.details_id from post p
where p.details_id = ?
I do not understand what is wrong here. Mapping is the same but LAZY
is ignored. Moreover the bidirectional association is loaded twice - one SELECT from each side.
SOLUTION UPDATE
In addition to Lukes's solution I would like to point out one Kotlin confusion: kotlin-jpa
plugin is surprisingly not enough to make JPA/Hibernate work properly. We had to configure kotlin-spring
plugin (which is a wrapper for all-open
plugin) and configure it to make @Entity open. This way, Hibernate can finally create proxy allowing lazy loading.
Upvotes: 3
Views: 1547
Reputation: 41
I've also noticed that the Kotlin scope function with()
will perform eager loading of lazy-loaded properties on the class.
@OneToMany(mappedBy = "book", cascade = [CascadeType.ALL], fetch = FetchType.LAZY, orphanRemoval = true)
open var chapters: MutableSet<Chapter> = mutableSetOf()
Using the with()
function
with(bookRepository.findById(bookId)) {
assertNotNull(this)
}
The chapters will be loaded eagerly. Whereas the following doesn't:
val book: Book? = bookRepository.findById(bookId)
assertNotNull(book)
Upvotes: 0
Reputation: 516
This is caused by kotlin classes. In order to fix it do as follow:
In your build.gradle
plugins section:
plugins {
kotlin("plugin.spring") version <kotlinVersion>
kotlin("plugin.jpa") version <kotlinVersion>
}
and at bottom of file
allOpen {
annotation("javax.persistence.Entity")
annotation("javax.persistence.MappedSuperclass")
annotation("javax.persistence.Embeddable")
}
this should fix the problem
Upvotes: 4