2011-10-05 23 views
0

考虑下面的例子:JPA - 一个与多个表之间共享主密钥的一种关系

我有3个表:水果,橙和苹果果表中生成

ID和是主键这里

ID也是Orange和苹果(共享主键)

所以对于如主键如果水果中的id是1,2,3,4,5 - 那么场景可能是1,2,橙色,3,4是苹果,而5又是橙色。

所以橙色表格会有id 1, 2,5而苹果表将有id为3,4

=================================== 
Fruit 
=================================== 
id  | shape 
=================================== 
    1  | round 
    2  | round 
    3  | oblong 
    4  | oblong 
    5  | round 
=================================== 


=================================== 
Orange 
=================================== 
id  | color | taste 
=================================== 
    1  | orange | sour 
    2  | orange | sour 
    5  | orange | sour 
=================================== 


=================================== 
Apple 
=================================== 
id  | density | weight 
=================================== 
    1  | hard  | 200 
    2  | hard  | 220 
    5  | hard  | 230 
=================================== 

问题:如何创建实体类捕获relationshipd也只有JPA注解(我不想使用Hibernate generatedValue注释)。

如果这样的注释是可能的纯JPA然后请指导我。

的Nik

+0

它看起来,你想要做的是继承(橙延伸水果和苹果 - >水果)。你有没有评估过这个选项? –

+0

这只是一个假设的例子。和不。没有继承关系。它更像雇员<->地址关系。每个员工将有一个地址,每个地址将只映射到一个员工。员工和地址的主键是共享的。 Means Employee_Id(这是Employee的主键)也是Address作为外键的主键。 – Nik

回答

0

为了通过迫使两个Java字段(ID和关联)来映射在同一列上进行测试。

例如,

class Orange { 

    @Id 
    @Column(name="id") 
    long id; 


    @OneToOne 
    @JoinColumn(name="id") 
    Fruit fruit; 

    public Orange(Fruit fruit) { 
     this.fruit = fruit; 
     this.id = fruit.id; 
    } 

    protected Orange() { } // default constructor required by JPA 
} 

但我不知道JPA提供者将如何表现。

2

您的情况看起来像设计模式的一个实例,称为“泛化专业化”(简称Gen-Spec)。如何使用数据库表建模gen-spec的问题始终在SO中出现。

如果您在OOPL(如Java)中对gen-spec进行建模,则可以使用子类继承功能来为您处理细节。您只需定义一个类来处理泛化对象,然后定义一个子类集合,每个专用对象类型都有一个。每个子类都会扩展广义类。这很简单直接。

不幸的是,据我所知,关系数据模型没有内置子类继承,而SQL数据库系统不提供任何这样的设施。但你并没有失败。您可以设计您的表格以与OOP的类结构相似的方式对gen-spec进行建模。当新项目添加到广义类时,您必须安排实现自己的继承机制。详情如下。

类结构相当简单,一个表为gen类,一个表为每个spec子类。这是来自Martin Fowler网站的一个很好的例子。 Class Table Inheritance。请注意,在该图中,Cricketer既是一个子类又是一个超类。你必须选择哪些属性放在哪个表中。该图显示了每个表中的一个示例属性。

棘手的细节是如何为这些表定义主键。 gen类表以通常的方式得到一个主键(除非这个表是另一个泛化的特殊化,比如Cricketers)。大多数设计师给主键一个标准名称,如“Id”。他们使用自动编号功能来填充Id字段。 spec类表获得一个主键,可以命名为“Id”,但不使用自动编号功能。相反,每个子类表的主键都被约束为引用广义表的主键。这使得每个专用主键都是外键以及主键。请注意,对于板球运动员来说,身份证字段将引用玩家中的身份证字段,但身边的身份证字段将引用玩家身份证号码中的身份字段。

现在,当您添加新项目时,您必须保持参照完整性,以下是方法。
您首先在gen表中插入新行,为除主键以外的所有属性提供数据。自动编号机制生成一个唯一的主键。接下来,将一个新行插入到适当的规范表中,包括其所有属性(包括主键)的数据。您使用的主键是刚生成的全新主键的副本。主键的传播可以称为“穷人的继承”。

现在,当您希望所有通用数据与来自一个子类的所有专用数据一起使用时,只需通过公用密钥将两个表连接起来即可。所有与该子类无关的数据将退出该连接。它光滑,简单,快速。

实现gen-spec模式的SQL表的设计可能有点棘手。数据库设计教程常常掩盖了这个主题。但它在实践中一次又一次地出现。

如果您在“泛化专业化关系建模”上搜索网页,您会发现几篇有用的文章,教您如何做到这一点。在这个论坛中,你也会被指出几次这个话题。

这篇文章通常会向您展示如何设计一个表来捕获所有通用数据和每个子类的一个专用表,这些表将包含特定于该子类的所有数据。有趣的部分涉及子类表的主键。您不会使用DBMS的自动编号功能来填充子类主键。相反,您将编写应用程序以将通用表中获得的主键值传播到适当的子类表中。

这在广义数据和专用数据之间建立了双向关联。每个专门的子类的简单视图将一起收集广义和专门的数据。一旦你掌握了它,它很容易,它表现相当好。

相关问题