Most Kotlin JPA example code looks like this
class Person(val name: String, val age: Int) { /* ... */ }
or even
data class Person(val name: String="", val age: Int=0) { /* ... */ }
Now, the Hibernate User Guide, and I think also several other ORMs, state that they usually want to create proxies or otherwise extend the model class, but to allow that in Kotlin the class has to be explicitly defined open
. This is currently impossible with data classes and I assume, judging from my own experience, that most people don't think about it when writing JPA entities in Kotlin.
So, to come to my question (this is stackoverflow after all), is it enough to do
open class Person(val name: String, val age: Int) { /* ... */ }
or would we actually have to do
open class Person(open val name: String, open val age: Int) { /* ... */ }
to not needlessly hinder the ORM at doing its job properly?
If it really is harmful, we should probably propose to add a warning to IntelliJ IDEA, that if a class is has an @Entity
annotation, it should be defined open
.
LAZY it is interpreted as a hint to the JPA provider that the loading of that field may be delayed until it is accessed for the first time: the property value in case of a @Basic annotation, the reference in case of a @ManyToOne or a @OneToOne annotation, or.
Rules for JPA Entities 1. The entity class must have a no-arg constructor. The entity class may have other constructors as well. The no-arg constructor must be public or protected.
enable_lazy_load_no_trans configuration parameter in the persistence. xml file to true. This parameter tells Hibernate to open a temporary Session when no active Session is available to initialize the lazily fetched association.
With a LAZY type dependency, only data of the wanted object is loaded: author's data is not retrieved. With Spring Data JPA, every relationship between 2 domain objects owns one of these data loading types. By default, the method will be determined by the relationship type.
The tutorial you provided specifies:
The entity class must have a public or protected no-argument constructor ... Interface may not be designated as an entity ... The entity class must not be final. No methods or persistent instance variables of the entity class may be final.
Kotlin classes follow the JavaBeans convention for setters/getters.
If your ORM has requirements as the above, then you indeed have to specify open
on the class and its methods:
open class Person(open val name: String = "",
open val age: Int = 0)
The default values for all of the constructor parameters allow Kotlin to generate an additional empty constructor. Alternatively you can provide it as a secondary constructor:
open class Person(open val name: String, open val age: Int) {
constructor() : this("", 0)
}
Note that open val
creates a private final field and an open getter. If that's not enough, use annotations like @JvmField open val name
.
ORMs like the on you use have additional friction with Kotlin code because of the questionable design patterns they use (like making everything non-final).
A good option is to use a Kotlin-specific ORM. For example Exposed is supported by JetBrains and used for some of its products, which speaks for itself. Another option is Ebean which officially supports Kotlin (thanks @johnp)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With