I’m trying to compose a JPA entity using class delegation (in a java+kotlin project) with no avail. I have something like this:
interface TestTrait : Serializable {
var traitValue: Int
}
@MappedSuperclass
open class TestTraitImpl : TestTrait {
override var traitValue: Int = 0
}
@MappedSuperclass
class TestMixin :
TestTrait by TestTraitImpl() {
var mixinValue: Int = 0
}
@Entity
@Table
public class TestEntity extends TestMixin {
@Id
@GeneratedValue
@Type(type = "uuid-char")
private UUID id;
private int entityValue;
public int getEntityValue() {
return entityValue;
}
public void setEntityValue(int entityValue) {
this.entityValue = entityValue;
}
}
Both entityValue
and mixinValue
are processed by Hibernate correctly, but traitValue
is not. Is class delegation fully supported by Hibernate/JPA? Am I missing something?
I can see that TestEntity
has a $$delegate_0
attribute, but Hibernate seems to ignore it. Is there some annotation I need to add to my TestTrait
or TestTraitImpl
so it can be processed by Hibernate?
Hi @totaltabardo, I think using Reflection instead of a annotation would work better with Hibernate.
Hi @miker256, thanks for the reply! Any idea on where to start? I’m not an expert on reflection by any means, but I have used it a few times in the pass to circumvent restrictions in libraries (similar to the problem here). In this case though, I’m trying to get my head around on how can I use reflection to solve this problem and I can’t think of anything. I’ll give it more thought and keep researching as I might have an eureka moment.
Found the solution!
It’s obvious now, but the problem was that I was using JPA field annotation instead of accessor. It all made sense after having a look at the bytecode that Kotlin was generating for the TestMixin
class.
This is the updated solution:
interface TestTrait {
@get:Column
var traitValue: Int
}
class TestTraitImpl : TestTrait {
override var traitValue: Int = 0
}
@MappedSuperclass
class TestMixin :
TestTrait by TestTraitImpl() {
@get:Column
var mixinValue: Int = 0
}
@Entity
@Table
public class TestEntity extends TestMixin {
private UUID id;
private int entityValue;
@Id
@GeneratedValue
@Type(type = "uuid-char")
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
@Column
public int getEntityValue() {
return entityValue;
}
public void setEntityValue(int entityValue) {
this.entityValue = entityValue;
}
}
I always preferred field annotation over accessor, but being able to use composition on my JPA entities is much more important!
After reading the article, Mixins Via Kotlin Delegation, and this forum post, I’m a little confused. According to the article, “mixed-in classes are compiled in to the class, implementing the mixin interface.” Maybe I’m misunderstanding something but if that’s the case why do you need TestMixin
?
Another followup, why is the final Entity in this example in Java and not Kotlin?
Thanks in advance.