Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在JPA中表达多态关联?_Jpa_Database Design_Modeling_Polymorphic Associations - Fatal编程技术网

如何在JPA中表达多态关联?

如何在JPA中表达多态关联?,jpa,database-design,modeling,polymorphic-associations,Jpa,Database Design,Modeling,Polymorphic Associations,A类似于外键或多对一关系,区别在于目标可能是多种类型(语言中的类、数据库中的表)中的一种 我正在将一个我已经使用多年的数据库设计从PHP移植到Java。在旧代码中,我使用了自己的ORM,但由于许多原因,它不是最优的。虽然我以后可能会开始调整一些东西,也许最终会自己实现一些东西,但现在我想在我的实体类上使用现成的ORM和JPA 现在,关于数据库布局有一点我不知道如何用JPA表达: 我有一个节点和一个边表来存储一个图形(DAG,如果有关系的话)。每个节点可以选择性地引用数据库中的另一个实体。这些实体

A类似于外键或多对一关系,区别在于目标可能是多种类型(语言中的类、数据库中的表)中的一种

我正在将一个我已经使用多年的数据库设计从PHP移植到Java。在旧代码中,我使用了自己的ORM,但由于许多原因,它不是最优的。虽然我以后可能会开始调整一些东西,也许最终会自己实现一些东西,但现在我想在我的实体类上使用现成的ORM和JPA

现在,关于数据库布局有一点我不知道如何用JPA表达:

我有一个
节点
和一个
表来存储一个图形(DAG,如果有关系的话)。每个节点可以选择性地引用数据库中的另一个实体。这些实体可能在整个图形中多次引用,也可能存在“孤立”实体,用户无法访问这些实体,但至少可以保留一段时间

这些对象在继承等方面根本不相关,但具有自然的层次结构,类似于Customer->Site->Floor->Room。事实上,几年前,我开始只使用指向“父”对象的外键字段。然而,这种层次结构不够灵活,开始分崩离析

例如,我想允许用户在文件夹中对对象进行分组,一些对象可以有多个“父对象”,并且关系会随着时间的推移而改变。我需要跟踪这些关系过去是如何的,所以图的edeg有一个与之相关联的时间跨度,它表示从何时到何时该边是有效的

从节点到对象的链接存储在节点表的两列中,一列包含外部表中的id,另一列包含其名称。例如(省略了某些列):

表节点:
+--------+-------+----------+
|ixNode | ixRef | sRefType|
+--------+-------+----------+

|1 | NULL | NULL |源表和系列表中存储了多少信息?只是一个名字吗?如果是这样,您可以将它们合并到一个表中,并添加一个“type”列。您的节点表将丢失其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

此表将替换源表和系列表。源和系列都属于超类吗?这是这张桌子的自然名称。

我想你已经找到了答案。创建一个抽象类(@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; 
}
@MappedSuperclass
@继承(策略=继承类型。每个类的表)
公共抽象类边{
// . . .
@独身癖
采集节点;
}
@实体
公共类源扩展了边缘{
}
@实体公共类系列扩展了边{
}
@实体
公共类节点{
// . . .
@许多酮
边缘;
}
我知道您可能不想暗示源代码和系列之间的关系,但是扩展一个公共抽象(无表)类是我能想到的实现您想要的功能的唯一方法

InheritanceType.TABLE_PER_类将源代码和序列保存在单独的表中(您可以使用单个_表执行类似于前面答案的操作)

如果这不是您想要的,那么许多JPA提供商提供了一个工具,可以基于现有的一组表创建映射。在OpenJPA中,它被称为反向映射工具[1]。该工具将生成Java源文件,您可以将其用作映射的起点。我怀疑Hibernate或EclipseLink也有类似的功能,但是您可以使用OpenJPA,并使用不同的提供者的实体定义(据我所知,该工具不会生成任何特定于OpenJPA的代码)

[1] 你看过注释了吗?它不是JPA的一部分,而是它的Hibernate注释扩展。

答案是:

  • 继承(正如Mike已经建议的那样)
  • 此外,还提供了以下信息:sxRef。我看到的唯一疑问是“sxRef”是一个可为空的列。我想这是禁止的

对不起,这对我不起作用。表格中有更多的信息,也有更多的表格,示例被简化。有许多不同类型的对象,我需要一个图形来更灵活地处理它们之间的关系。也许,我可以设想某种抽象的RelatedEntity和一个存储键值对的通用属性表,但这似乎有点过分了。我在数据库中几乎没有结构化信息了。虽然这似乎至少接近我想要的,但我现在不使用Hibernate,我也不想切换,也不想为我的应用程序的这样一个核心元素绑定到特定的提供者+这很容易实现,但我没有得到的是:持久性提供者如何知道将哪个类实例化为节点中特定行的引用对象?好问题。我已经用OpenJPA对这个解决方案进行了建模(其他供应商的方法可能有所不同)。OpenJPA在节点表中存储一个字符串,该字符串包含边缘的类名和PK。基本上,它将ixRef+sRefType组合到一个列中。我不确定如何说服JPA提供商使用您当前拥有的表定义(不过,ReverseMappingTool或类似的工具可能会解决这个问题)。我假设您需要保持现有表的完整性,而这种方法不适合您?不,我可以随意调整模式,我只是好奇(或者称之为怀疑:-))。看来这就是解决办法了。我仍然想知道,如果让一个提供者设置数据库,然后更改提供者,会发生什么情况。但我想这是你推迟到你
@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; 
}