【问题标题】:@Embeddable class with val in Kotlin在 Kotlin 中使用 val 的 @Embeddable 类
【发布时间】:2017-09-30 06:29:31
【问题描述】:

我正在从事 Gradle-Kotlin-Hibernate 项目。我想让我的一些类不可变,这在 Kotlin 中特别容易。这适用于 @Entity

@Entity(name = "SOMETHING")
class MeetingKeychain(
        val immutableProp: String
) {

// ID and others

}

感谢kotlin-jpa插件的使用。但同样的插件不适用于 @Embeddable

@Embeddable
class MeetingKeychain(
        val immutableProp: String
) {

// ID and others

}

抛出以下异常:

Caused by: org.hibernate.HibernateException: Unable to instantiate default tuplizer [org.hibernate.tuple.component.PojoComponentTuplizer]
    at org.hibernate.tuple.component.ComponentTuplizerFactory.constructTuplizer(ComponentTuplizerFactory.java:98)
    at org.hibernate.tuple.component.ComponentTuplizerFactory.constructDefaultTuplizer(ComponentTuplizerFactory.java:119)
    at org.hibernate.tuple.component.ComponentMetamodel.<init>(ComponentMetamodel.java:64)
    at org.hibernate.mapping.Component.getType(Component.java:169)
    at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:398)
    at org.hibernate.mapping.Property.isValid(Property.java:225)
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:595)
    at org.hibernate.mapping.RootClass.validate(RootClass.java:265)
    at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:443)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879)
    ... 46 more
Caused by: java.lang.reflect.InvocationTargetException
    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.tuple.component.ComponentTuplizerFactory.constructTuplizer(ComponentTuplizerFactory.java:95)
    ... 56 more
Caused by: org.hibernate.PropertyNotFoundException: Could not locate setter method for property [com.scherule.calendaring.domain.entities.ParticipantId#id]
    at org.hibernate.internal.util.ReflectHelper.findSetterMethod(ReflectHelper.java:540)
    at org.hibernate.property.access.internal.PropertyAccessBasicImpl.<init>(PropertyAccessBasicImpl.java:44)
    at org.hibernate.property.access.internal.PropertyAccessStrategyBasicImpl.buildPropertyAccess(PropertyAccessStrategyBasicImpl.java:27)
    at org.hibernate.mapping.Property.getGetter(Property.java:299)
    at org.hibernate.tuple.component.PojoComponentTuplizer.buildGetter(PojoComponentTuplizer.java:143)
    at org.hibernate.tuple.component.AbstractComponentTuplizer.<init>(AbstractComponentTuplizer.java:46)
    at org.hibernate.tuple.component.PojoComponentTuplizer.<init>(PojoComponentTuplizer.java:42)
    ... 61 more

我的问题是有没有办法解决这个问题?我希望我的 @Embeddable 类是不可变的。

【问题讨论】:

  • 可能和这个bug有关。

标签: java hibernate kotlin


【解决方案1】:

实际上这被证明是可行的,并且与 Kotlin 无关。它相关的唯一方法是您需要生成默认构造函数,该构造函数用于 kotlin-jpa 插件。你需要使用

@Access(AccessType.FIELD)

同时

@Access(AccessType.PROPERTY)

是默认值。然后它会寻找 setter 而不是使用字段注入。

【讨论】:

  • 不,kotlin-jpa 还处理 val 属性以允许休眠使用此类类而无需 setter,并且它在常规 @Entity 类上完美运行
  • @krzychek 我在没有字段访问的情况下遇到了同样的错误。通过添加字段访问解决了。您可以为您的项目共享实体 sn-p 和 gradle/maven 配置吗?
  • 我目前无法访问任何配置了 kotlin + jpa 的项目。你有应用 kotlin-jpa 插件吗?
  • @Access(AccessType.PROPERTY) 似乎是带有 val(而不是 var)字段的嵌入项所必需的,即使 Kotlin JPA 插件正在使用中。所以,这个建议的解决方案解决了这个问题。
【解决方案2】:

我猜这是休眠限制。它清楚地写着Could not locate setter method for property。所以我们应该为他提供二传手。唯一的方法是将val 更改为var。 即使我们在插件配置中添加@Embeddable 注解,no-arg 插件也无济于事: noArg { invokeInitializers = true annotation("javax.persistence.Embeddable") }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    相关资源
    最近更新 更多