【问题标题】:Sealed class as an entity密封类作为一个实体
【发布时间】:2020-01-13 13:29:36
【问题描述】:

我正在尝试解决我的 kotlin 密封类的继承问题和休眠的强制问题。

这是我的课程:

@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()

这是抛出的问题:

原因:org.hibernate.MappingException:无法获取 org.hibernate.persister.entity.SingleTableEntityPersister 的构造函数 在 org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:123) 在 org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:77) 在 org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:348) 在 org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) 在 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) ...省略了95个常用框架 引起:org.hibernate.InstantiationException:无法实例化测试对象:X.MotherLegalGuardian 在 org.hibernate.engine.internal.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:43) 在 org.hibernate.engine.internal.UnsavedValueFactory.getUnsavedIdentifierValue(UnsavedValueFactory.java:68) 在 org.hibernate.tuple.PropertyFactory.buildIdentifierAttribute(PropertyFactory.java:61) 在 org.hibernate.tuple.entity.EntityMetamodel.(EntityMetamodel.java:141) 在 org.hibernate.persister.entity.AbstractEntityPersister.(AbstractEntityPersister.java:517) 在 org.hibernate.persister.entity.SingleTableEntityPersister.(SingleTableEntityPersister.java:124) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:423) 在 org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:96) ... 99个常用框架省略 引起:java.lang.reflect.InvocationTargetException:null 在 sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 在 sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.lang.reflect.Constructor.newInstance(Constructor.java:423) 在 org.hibernate.engine.internal.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:40) ...省略了109个常用框架 引起:java.lang.NoSuchMethodError: X.LegalGuardian.(Lkotlin/jvm/internal/DefaultConstructorMarker;)V 在 X.MotherLegalGuardian.(LegalGuardian.kt) ... 省略了 114 个常用帧

【问题讨论】:

    标签: spring hibernate jpa kotlin spring-data-jpa


    【解决方案1】:

    我不知道休眠是如何工作的。 但我想这个问题与sealed-classes docs的这个注释有关:

    一个密封的类本身是抽象的,它不能被实例化 直接并且可以有抽象成员。

    密封类不允许有非私有的构造函数(它们的 构造函数默认是私有的)。

    【讨论】:

    • 那么你会使用带有公共构造函数的抽象类吗?
    • 对不起老兄,我说过我对此一无所知。
    【解决方案2】:

    看起来问题不在于密封类,而在于数据类和构造函数。当您使用带参数的主构造函数时,没有默认(无参数)构造函数,这是休眠所必需的。您可以在堆栈跟踪的最后看到原因:

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

    您可以启用no-argjpa-support 插件来生成无参数构造函数。

    还可以查看this article,它解释了为什么数据类不是休眠的好选择。

    【讨论】:

    • 我删除了数据类但没有帮助。同样的错误
    • 即使您不使用数据类,您也需要启用提到的插件以生成无参数构造函数,因为您的类没有无参数构造函数。编辑了答案以使其更清晰。
    猜你喜欢
    • 2017-11-08
    • 2020-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多