派生数据库结构的优秀设计是什么?

时间:2014-11-20 11:13:22

标签: java design-patterns database-design derived-class

填写表格的输入是一个大文件,它有唯一的animalIds,它们的名字,动物类型和其他一些动物类型的特定值。

数据库如下所示:

table animal:
- animalId(pk)
- name
- type(fk to animalType table)   

table dogs:         
- dogId(pk)         
- animalId(fk to animal)    
- hasCoat           
- etc...            

table fish:
- fishId(pk)
- animalId(fk to animal)
- animalId(fk to animal)
- dorsalFinCount
- etc...

我是这样设计的,因为我的另一个来源给了我一个独特的键(animalId,它识别世界各地的单一动物......就像一个uri)而且我不想拥有一个空值的大型单一数据库(例如,对于hasCoat和hasDorsalFin)也不必连续​​搜索两个类型特定的数据库。 此外,我可以轻松地扩展这个结构(表鸟,具有属性hasWing,wingColor等...)

我的(Java)程序设计如下所示:

abstract class Animal
- animalId
- name
- type

class Dog extends DatabaseObject 
class Fish extends DatabaseObject 

abstract class DatabaseObject 
    private UUID id;
    public DatabaseObject(){this.uuid = UUID.randomUUID();}
    public UUID getId();

问题是,Dog和Fish类是Animal,但需要为每个数据库条目设置一个UUID,因为在动物表中使用唯一的animalId作为PK。 此外,Dog和Fish也应该扩展Animal,因为它们需要那些数据字段......但这在Java中是不可能的,因为它们都已经扩展了抽象的DatabaseObject类。

一个解决方案可能是,Dog和Fish将Animal字段作为类成员,但这似乎是一个糟糕的方法。

您如何解决此问题以及您的设计(数据库和程序结构)的优点是什么?

修改 由于我的假设(...... PK不能用作另一张表中的PK)是错误的,我可以将dogId和fishId改为animalId。此外,这种数据库设计称为subtyping

2 个答案:

答案 0 :(得分:2)

不要重新发明轮子,使用ORM。如果您可以使用Hibernate,那么已经有Inheritance Mapping功能。

答案 1 :(得分:1)

您的设计类似于称为类表继承的设计模式。你可以在这里访问同名的标签,或者你可以通过在网上搜索看到Martin Fowler对同一主题的处理。

我建议你做一个小改动。它可能适用于您的情况,也可能不适用。它被称为“共享主键”。你摆脱了DogId和FishId。相反,你将AminalID作为狗和鱼桌以及动物桌的PK。请注意,AnimalID将是PK和FK。当然,你必须让它成为动物PK的真实副本。

这有几个优点,其中包括简单性和速度。但最大的优点是它强制执行每个子类和超类之间的IS-A关系的一对一性质。