如何处理关系数据库中的继承
How to handle inheritance in a relational database
我在理解继承如何与关系数据库一起工作时遇到了一些困难。
假设我有以下 类:
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 ...
}
火车由组件(列表)组成,并且有多个子组件类(本例中只有货车)。
为了坚持这一点,我认为 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;
所以现在我想创建一个 DAO 方法,returns 一个包含所有组件的 Train 对象。我可以通过它的 ID 查询火车并使用 train_fk 在组件 table 中查找相应的组件,但这就是问题开始的地方。 Component
table 仅包含我需要的部分数据(对于 Wagon obj,其余信息位于 Wagon
table 中)。
在这种情况下,很明显我需要查询 Wagon
table 以获取其余信息,但如果我有更多类型怎么办。我如何知道要查询什么 table 以及要解析到什么对象?
我知道这在当前结构下是不可能的,但通常如何做到这一点?在关系数据库中处理此类继承的标准解决方案是什么?
提前致谢!
PS:我试图在不使用 JPA、Hibernate 或任何其他框架的情况下执行此操作,只是 JDBC ;)
我建议在组件 table 上添加一列来指示子类型。
然后当您使用组件和所有子类型加入训练时,您可以在 Java 端确定您必须实例化什么类型。
第二个选项可以是 select 中的 case 语句:
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
我在理解继承如何与关系数据库一起工作时遇到了一些困难。
假设我有以下 类:
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 ...
}
火车由组件(列表)组成,并且有多个子组件类(本例中只有货车)。
为了坚持这一点,我认为 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;
所以现在我想创建一个 DAO 方法,returns 一个包含所有组件的 Train 对象。我可以通过它的 ID 查询火车并使用 train_fk 在组件 table 中查找相应的组件,但这就是问题开始的地方。 Component
table 仅包含我需要的部分数据(对于 Wagon obj,其余信息位于 Wagon
table 中)。
在这种情况下,很明显我需要查询 Wagon
table 以获取其余信息,但如果我有更多类型怎么办。我如何知道要查询什么 table 以及要解析到什么对象?
我知道这在当前结构下是不可能的,但通常如何做到这一点?在关系数据库中处理此类继承的标准解决方案是什么?
提前致谢!
PS:我试图在不使用 JPA、Hibernate 或任何其他框架的情况下执行此操作,只是 JDBC ;)
我建议在组件 table 上添加一列来指示子类型。
然后当您使用组件和所有子类型加入训练时,您可以在 Java 端确定您必须实例化什么类型。
第二个选项可以是 select 中的 case 语句:
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