Issue
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
.
Solution
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)
Answered By - voddan