如何处理关系数据库中的继承

时间:2017-12-11 11:43:37

标签: java mysql inheritance relational-database dao

我在理解继承如何与关系数据库一起工作时遇到了一些困难。

假设我有以下类:

public class Train {
    private int id;
    private String callsign;
    private List<Component> components = new ArrayList<Component>();

    public Train(){}

    public Train(String callsign){
        this.callsign = callsign;
    }
    ... getters & setters ...  
}

public abstract class Component {
    private int id;

    private String callsign;


    private Train train;

    public Component() {
    }

    public Component(String callsign) {
        this.callsign = callsign;
    }

    ... getters & setters ...  

}

public class Wagon extends Component{
    private int numOfSeats;

    public Wagon(String callsign, int numOfSeats) {
        super(callsign);
        this.numOfSeats = numOfSeats;
    }

    public Wagon() {
    }
    ... getters & setters ...  
}

一个Train是由组件(List)构建的,并且有多个组件子类(在这个例子中只有Wagon)。

为了坚持这一点,我认为Table Per Type Inheritance结构是合适的,但这是我遇到问题的地方。

我的数据库结构:

CREATE TABLE `Train` (
  `id` int(11) NOT NULL,
  `callsign` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_callsign_train` (`callsign`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `Component` (
  `id` int(11) NOT NULL,
  `callsign` varchar(255) NOT NULL,
  `train_FK` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UK_callsign_comp` (`callsign`),
  KEY `FK_comp_train` (`train_FK`),
  CONSTRAINT `FK_comp_train` FOREIGN KEY (`train_FK`) REFERENCES `Train` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `Wagon` (
  `numOfSeats` int(11) NOT NULL,
  `id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `FK_wagon_comp` FOREIGN KEY (`id`) REFERENCES `Component` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

所以现在我想创建一个返回Train对象的DAO方法,该对象包括它的所有组件。我可以通过它的ID查询Train,并使用train_fk在Component表中查找相应的组件,但这就是麻烦开始的地方。 Component表仅部分保存我需要的数据(在Wagon obj的情况下,其余信息存在于Wagon表中)。

在这种情况下,显而易见的是,我需要在Wagon表中查询其余信息,但如果我有更多类型,该怎么办?如何知道要查询的表以及要解析的对象?

我知道目前的结构是不可能的,但这是如何正常完成的?在关系数据库中处理这种继承的标准解决方案是什么?

提前致谢!

PS:我试图在不使用JPA,Hibernate或任何其他框架的情况下尝试这样做,只需使用JDBC;)

1 个答案:

答案 0 :(得分:1)

我建议在Component表上添加一个指示子类型的列。

当您使用组件和所有子类型加入train时,您可以在Java端识别您需要实例化的类型。

第二个选项可以是选择中的案例陈述:

select *,
       case 
         when w.id is not null then 'wagon' 
       end as type 
from train t 
  join component c on c.train_FK = t.id
  left outer join Wagon w on w.id = c.id