When generating Spring project with Kotlin and JPA options it creates a maven / gradle config with "jpa" and "spring" plugins:
...
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<compilerPlugins>
<plugin>spring</plugin>
<plugin>jpa</plugin>
...
But to enable Hibernate to generate proxies for Entity classes it must create "all-open" plugin config for them as well:
...
<compilerPlugins>
<!-- no-arg constructor for jpa entities -->
<plugin>jpa</plugin>
<!-- open @Component, @Async, @Transactional, @Cacheable and @SpringBootTest classes -->
<plugin>spring</plugin>
<!-- open Entities to let them using Lazy with ManyToOne -->
<plugin>all-open</plugin>
</compilerPlugins>
<pluginOptions>
<!-- open Entities to let them using Lazy with ManyToOne -->
<option>all-open:annotation=javax.persistence.Entity</option>
<option>all-open:annotation=javax.persistence.Embeddable</option>
<option>all-open:annotation=javax.persistence.MappedSuperclass</option>
</pluginOptions>
...
We can see the same config in Spring Boot + Kotlin tutorial on the official website. Also there was a discussion about adding this behaviour in "jpa" plugin in KT-28594
Otherwise we easily get into N+1 problem when querying an entity collection with @ManyToOne mapping in it:
@Entity
@Table(name = "commits")
class Commit(
@Id var id: Int = 0,
var hash: String? = null,
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "author_id")
var author: Author
)
@Table(name = "authors")
@Entity
class Author (
@Id var id: Int = 0,
@OneToMany(mappedBy = "author")
var commits: MutableList<Commit> = mutableListOf()
)
interface CommitRepository : JpaRepository<Commit, Int>
Calling commitRepository.findAll() causes Hibernate to fetch firstly all commits and then, as it fails to create a proxy for the mapped fields, their authors, each in a separate query. Moreover, if commit has other @ManyToOne mappings - they'd go in a separate query too, and if author has it's own @ManyToOne mappings ...you know where it leads.
When I select Java to use in a generated project this lazy fetch behavior is supported out-of-the-box due to the fact that all classes in Java are "open" from Kotlin perspective.
So I am absolutely sure that this config should be added in standard Kotlin + Spring Data JPA project initializr as I constantly see how such applications go in production causing enormous overhead there😩
When generating Spring project with Kotlin and JPA options it creates a maven / gradle config with "jpa" and "spring" plugins:
But to enable Hibernate to generate proxies for Entity classes it must create "all-open" plugin config for them as well:
We can see the same config in Spring Boot + Kotlin tutorial on the official website. Also there was a discussion about adding this behaviour in "jpa" plugin in KT-28594
Otherwise we easily get into N+1 problem when querying an entity collection with
@ManyToOnemapping in it:Calling
commitRepository.findAll()causes Hibernate to fetch firstly all commits and then, as it fails to create a proxy for the mapped fields, their authors, each in a separate query. Moreover, if commit has other@ManyToOnemappings - they'd go in a separate query too, and if author has it's own@ManyToOnemappings ...you know where it leads.When I select Java to use in a generated project this lazy fetch behavior is supported out-of-the-box due to the fact that all classes in Java are "open" from Kotlin perspective.
So I am absolutely sure that this config should be added in standard Kotlin + Spring Data JPA project initializr as I constantly see how such applications go in production causing enormous overhead there😩