自引用 JPA 实体以满足接口定义
Self referencing JPA Entity to satisfy interface definition
我有一个 spring + Data JPA 设置,其中包含几个继承自接口定义的实体,如下所示(“伪”Java):
@Entity
A implements WithSubProperty
@Id
Long Id
SubProperty subProperty
…
@Entity
B implements WithSubProperty
@Id
Long Id
SubProperty subProperty
…
Interface WithSubProperty
SubProperty subProperty
…
@Entity
SubProperty
@Id
Long Id
…
每个实体都有自己的 table。
此外,还有几个使用接口定义的存储库片段(为了兼容 类 只实现自定义逻辑一次),如下所示:
RepositoryFragment<WithSubProperty, K>
List<WithSubProperty> findAllWithSubProperty(SubProperty subProperty)
…
现在,我想以相同的方式处理实际接口 属性(子属性),而不必为此单个实体复制和调整 RepositoryFragment 逻辑。我尝试了以下方法(在 SubProperty 上使用了几种不同的注释(@OneToOne、@Transient、@Column、@JoinColumm、@Formula 及其组合):
@Entity
SubProperty implements WithSubProperty
@Id
Long Id
@XXXAnnotations
SubProperty subProperty
一个想法是引用 id 列,基本上形成与自身的 OneToOne 关系。到目前为止,我无法让它工作。
乍一看,这种方法看起来有点笨拙,但除了 JPA/Hibernate 可能(?)缺乏支持和以递归结束的风险之外,应该没有其他问题。想法?谢谢!
更新:
这是一个最小的(不是)工作示例:https://github.com/user462982/demoJPA/blob/master/src/main/java/com/example/demo/entities/SubProperty.java
对于上述代码可能造成的混淆,我们深表歉意。我的原始代码是在 Kotlin 中,我试图从我的头顶将它翻译成 Java 而没有 anticipating/considering 样板文件 Java 是如何真正得到的(例如 [=28] 中没有接口属性=])...
希望工作示例现在可以使它更清楚。它在启动时创建相同的异常,所以我假设(字节)代码是等效的。
最后我找到了解决方案:https://github.com/user462982/selfReferencingJPAEntity/blob/master/src/main/kotlin/ex/ample/selfreferencing/entites/Property.kt
(这次在 Kotlin 中,因为 Java 实在是太多了...)。
基本上
@OneToOne(获取=FetchType.LAZY)
@JoinColumn(name = "id")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id", insertable=false, updatable =false)
够了:
@Entity class Property : WithProperty {
@Id
@GeneratedValue
val id: Long? = null
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id", insertable=false, updatable =false)
override val property: Property? = null
理解问题的一个很好的起点是测试:https://github.com/user462982/selfReferencingJPAEntity/blob/master/src/test/kotlin/ex/ample/selfreferencing/repositories/RepositoriesTest.kt
该测试还揭示了 org.hibernate.loader.hql.QueryLoader 中的一个错误,如果参数在具有上述自引用实体的查询中多次出现,该错误似乎会让人感到困惑。
休眠问题是由@OneToOne关联引起的,可以通过使用上述@ManyToOne来解决。
我有一个 spring + Data JPA 设置,其中包含几个继承自接口定义的实体,如下所示(“伪”Java):
@Entity
A implements WithSubProperty
@Id
Long Id
SubProperty subProperty
…
@Entity
B implements WithSubProperty
@Id
Long Id
SubProperty subProperty
…
Interface WithSubProperty
SubProperty subProperty
…
@Entity
SubProperty
@Id
Long Id
…
每个实体都有自己的 table。 此外,还有几个使用接口定义的存储库片段(为了兼容 类 只实现自定义逻辑一次),如下所示:
RepositoryFragment<WithSubProperty, K>
List<WithSubProperty> findAllWithSubProperty(SubProperty subProperty)
…
现在,我想以相同的方式处理实际接口 属性(子属性),而不必为此单个实体复制和调整 RepositoryFragment 逻辑。我尝试了以下方法(在 SubProperty 上使用了几种不同的注释(@OneToOne、@Transient、@Column、@JoinColumm、@Formula 及其组合):
@Entity
SubProperty implements WithSubProperty
@Id
Long Id
@XXXAnnotations
SubProperty subProperty
一个想法是引用 id 列,基本上形成与自身的 OneToOne 关系。到目前为止,我无法让它工作。 乍一看,这种方法看起来有点笨拙,但除了 JPA/Hibernate 可能(?)缺乏支持和以递归结束的风险之外,应该没有其他问题。想法?谢谢!
更新: 这是一个最小的(不是)工作示例:https://github.com/user462982/demoJPA/blob/master/src/main/java/com/example/demo/entities/SubProperty.java
对于上述代码可能造成的混淆,我们深表歉意。我的原始代码是在 Kotlin 中,我试图从我的头顶将它翻译成 Java 而没有 anticipating/considering 样板文件 Java 是如何真正得到的(例如 [=28] 中没有接口属性=])... 希望工作示例现在可以使它更清楚。它在启动时创建相同的异常,所以我假设(字节)代码是等效的。
最后我找到了解决方案:https://github.com/user462982/selfReferencingJPAEntity/blob/master/src/main/kotlin/ex/ample/selfreferencing/entites/Property.kt (这次在 Kotlin 中,因为 Java 实在是太多了...)。
基本上
@OneToOne(获取=FetchType.LAZY)
@JoinColumn(name = "id")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id", insertable=false, updatable =false)
够了:
@Entity class Property : WithProperty {
@Id
@GeneratedValue
val id: Long? = null
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id", insertable=false, updatable =false)
override val property: Property? = null
理解问题的一个很好的起点是测试:https://github.com/user462982/selfReferencingJPAEntity/blob/master/src/test/kotlin/ex/ample/selfreferencing/repositories/RepositoriesTest.kt
该测试还揭示了 org.hibernate.loader.hql.QueryLoader 中的一个错误,如果参数在具有上述自引用实体的查询中多次出现,该错误似乎会让人感到困惑。
休眠问题是由@OneToOne关联引起的,可以通过使用上述@ManyToOne来解决。