polymorphic association类似于外键或多对一关系,不同之处在于目标可能是多种类型之一(语言中的类,数据库中的表)。
我正在移植一个数据库设计,我已经使用了几年,从PHP到Java。在旧的代码中,我已经推出了自己的ORM,由于多种原因这不是最佳的。虽然我可能会在以后开始调整内容,也许最终会自己再次实现,现在我想在我的实体类中使用现成的ORM和JPA。
现在,关于数据库布局有一点我不知道如何在JPA中表达:
我有一个Node
和一个Edge
表存储图表(DAG,如果重要的话)。每个节点可以可选地从数据库引用另一个实体。这些实体可能会在整个图表中被多次引用,也可能存在“孤儿”,这对用户来说是不可访问的,但至少可以保留一段时间是有意义的。
这些对象在继承等方面完全没有关系,但具有自然层次结构,类似于Customer-> Site-> Floor-> Room。事实上,几年前,我开始只使用指向“父”对象的外键字段。但是,这种层次结构不够灵活,而且开始分崩离析。
例如,我想允许用户将文件夹中的对象分组,某些对象可以有多个“父母”,并且关系也会随着时间而变化。我需要跟踪过去的关系,因此图的edegs有一个与它们相关的时间跨度,表明从何时到该边缘有效。
从节点到对象的链接存储在节点表的两列中,一个在外表中携带id,一个携带其名称。例如(省略了一些列):
table Node:
+--------+-------+----------+
| ixNode | ixRef | sRefType |
+--------+-------+----------+
| 1 | NULL | NULL | <-- this is what a "folder" would look like
| 2 | 17 | Source |
| 3 | 58 | Series | <-- there's seven types of related objects so far
+--------+-------+----------+
table Source (excerpt):
+----------+--------------------+
| ixSource | sName |
+----------+--------------------+
| 16 | 4th floor breaker |
| 17 | 5th floor breaker |
| 18 | 6th floor breaker |
+----------+--------------------+
可能存在与使用JPA不同的解决方案。我可以改变一些关于表格布局的东西或者引入一个新的表格等等。但是,我已经考虑了很多这个并且表格结构对我来说似乎没问题。也许还有第三种方式,我没有想到。
答案 0 :(得分:5)
我想你已经找到了答案。创建一个抽象类(@Entity或@MappedSuperclass)并使用不同的类型扩展它。
这样的事情可能会起作用
@MappedSuperclass
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class Edge {
// . . .
@OneToMany
Collection<Node> nodes;
}
@Entity
public class Source extends Edge {
}
@Entity public class Series extends Edge {
}
@Entity
public class Node {
// . . .
@ManyToOne
Edge edge;
}
我知道你可能不想暗示Source和Series之间的关系,但扩展一个共同的抽象(无表格)类是我能想到做你想做的事情的唯一方法。
InheritanceType.TABLE_PER_CLASS会将Source和Series保存在不同的表中(您可以使用SINGLE_TABLE执行类似上一个答案的操作)。
如果这不是您正在寻找的,许多JPA提供程序提供了一个基于现有表集创建映射的工具。在OpenJPA中,它被称为ReverseMappingTool [1]。该工具将生成Java源文件,您可以将其用作映射的起点。我怀疑Hibernate或EclipseLink有类似的东西,但您可以使用OpenJPA并使用不同的提供程序的实体定义(据我所知,该工具不生成任何OpenJPA特定代码)。
[1] http://openjpa.apache.org/builds/latest/docs/manual/manual.html#ref_guide_pc_reverse
答案 1 :(得分:5)
答案是:
答案 2 :(得分:2)
你看过@Any注释了吗?它不是JPA的一部分,但它是Hibernate Annotation的扩展。
答案 3 :(得分:0)
Source和Series表中存储了多少信息?这只是一个名字吗?如果是这样,您可以将它们组合到一个表中,并添加“类型”列。您的Node表将丢失其sRefType,并且您将拥有一个如下所示的新表:
ixSource sName sType
16 4th floor breaker SOURCE
17 5th floor breaker SOURCE
18 6th floor breaker SOURCE
19 1st floor widget SERIES
20 2nd floor widget SERIES
此表将替换Source和Series表。 Source和Series都属于超类吗?这将是这张桌子的自然名称。