hibernate - 自引用 JPA 实体以满足接口定义
问题描述
我有一个 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
…
每个实体都有自己的表。此外,还有几个使用接口定义的存储库片段(为了只为兼容的类实现一次自定义逻辑),如下所示:
RepositoryFragment<WithSubProperty, K>
List<WithSubProperty> findAllWithSubProperty(SubProperty 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,而没有预料/考虑样板 Java 的真正获取方式(例如,Java 中没有接口属性)......希望工作示例现在更清楚. 它在启动时会创建相同的异常,因此我假设(字节)代码是等效的。
解决方案
最后我找到了一个解决方案:https://github.com/user462982/selfReferencingJPAEntity/blob/master/src/main/kotlin/ex/ample/selfreferencing/entites/Property.kt (这次是在 Kotlin 中,因为 Java 是皮塔饼太多了……)。
基本上
@OneToOne(fetch = 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 来解决。
推荐阅读
- python - 基本 Python:使用 Jupyter Notebook 的方程式和绘图不起作用
- mysql - 在 Squalize 的 FROM 子句中指定子查询
- c# - 序列化“System.Data.Entity.DynamicProxies.Item”类型的对象时检测到循环引用
- pygame - 我如何在这个 pygame 屏幕上添加一个用鼠标画线的函数
- python-3.x - 如何使用 numpy 在 Python 中定义分段函数?
- python - 在函数中循环 5 位数字的数字
- multithreading - Jmeter tearDown Thread Group 无法访问之前使用过的线程组文件
- c - 确定两个无符号 int32 的大小差异(以字节为单位)
- android - DJI 遥控器数据为空
- javascript - 为什么如果我得到计算对象中的对象属性未定义而不是对象本身?哪种方法更适合这种情况?