3
votes

I'm trying to solve my inheritance problem with kotlin sealed class and forced problem with hibernate.

Here are my classes:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
sealed class LegalGuardian(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Int? = null
)

@Entity
@DiscriminatorValue(value = "MOTHER")
data class MotherLegalGuardian(
    @OneToOne(cascade = [CascadeType.ALL], orphanRemoval = true)
    val pesel: Pesel
) : LegalGuardian()

@Entity
@DiscriminatorValue(value = "OTHER")
data class OtherLegalGuardian(
    val firstName: String,
    val lastName: String,
    @OneToOne
    val address: Address
) : LegalGuardian()

Here is poroblem that is thrown:

Caused by: org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:123) at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:77) at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:348) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) ... 95 common frames omitted Caused by: org.hibernate.InstantiationException: could not instantiate test object : X.MotherLegalGuardian at org.hibernate.engine.internal.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:43) at org.hibernate.engine.internal.UnsavedValueFactory.getUnsavedIdentifierValue(UnsavedValueFactory.java:68) at org.hibernate.tuple.PropertyFactory.buildIdentifierAttribute(PropertyFactory.java:61) at org.hibernate.tuple.entity.EntityMetamodel.(EntityMetamodel.java:141) at org.hibernate.persister.entity.AbstractEntityPersister.(AbstractEntityPersister.java:517) at org.hibernate.persister.entity.SingleTableEntityPersister.(SingleTableEntityPersister.java:124) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:96) ... 99 common frames omitted Caused by: java.lang.reflect.InvocationTargetException: null at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.hibernate.engine.internal.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:40) ... 109 common frames omitted Caused by: java.lang.NoSuchMethodError: X.LegalGuardian.(Lkotlin/jvm/internal/DefaultConstructorMarker;)V at X.MotherLegalGuardian.(LegalGuardian.kt) ... 114 common frames omitted

2

2 Answers

0
votes

I don't know how hibernate works. But I guess the issue is related to this notes from sealed-classes docs:

A sealed class is abstract by itself, it cannot be instantiated directly and can have abstract members.

Sealed classes are not allowed to have non-private constructors (their constructors are private by default).

0
votes

It looks like the problem is not in sealed class, but in the data class and constructors. When you are using primary constructors with arguments, there is no default (no-arguments) constructor, which is required for hibernate. You can see the reason in the very end of the stacktrace:

java.lang.NoSuchMethodError: X.LegalGuardian.(Lkotlin/jvm/internal/DefaultConstructorMarker;)V at X.MotherLegalGuardian.(LegalGuardian.kt)

You can enable no-arg and jpa-support plugins to get no-arg constructors generated.

Check out also this article which explains why data classes are not a good choice for hibernate.