情景如下:一个学员有两类员工,老师和后勤人员.员工有id和姓名,老师还额外有个授课学科,用OO来表达如下
class Staff{
private String id;
private String name;
}
class Teacher extends Staff{
private String subject;
}
首先第一个问题是否要专门建一个后勤员工这个类.应该是很有必要的.从类的角度来看即使一个类拥有另一个内的所有方法也并不意味着相同方法类的内部实现会相同.如果把这个方法写到父类则有些不妥.
那么下一个问题是数据库如何设计.一般有三类方案
方案一:为父类建一张表,提供子类所有的字段然后再加上一个标识来表明是哪个子类.那么这张表将有很多字段并且可能很多字段的值都是空的.有的时候可以明确知道join的是老师那么也需要join员工这个大表,影响性能
方案二:为每个子类建立一张表.这样不会有冗余字段但带来的问题是查询时会有union操作,也会影响性能,并且无法做外键约束
方案三是上面两种方案的综合.创建N+1张表,为每个子类创建一张表,再为那些公共字段创建一个表也就是父表.至于子类表是否需要冗余存储父类表的字段则可以再分为方案3.1和方案3.2我的看法是根据查询需要来,尽量不要出现父类表join子类表的情况.但这只是继承关系只有一级的情况,万一由来个班主任继承Teacher,那就是(M(N+1)+1)张表了.几乎所有类,不管是父类还是子类都需要有一张表.
对于postgresql由于原生的提供了inherit的概念,所以在上面第三个方案上只需要真子类的NM张表,而不需要父类M+1表.真实的存储应该是和方案二类似,也就是查父类表的时候通过union子类来实现的,只是数据自动帮我们完成了这个视图.这也意味着有这方面的性能损失.postgresql的inherit还支持多重继承,这就解决了一些在java中要靠接口来解决的问题.
在前一个问题的后面还有一个紧密跟着的问题:对于一些字段和父类一样的子类是否需要专门建立一张表呢?如果从数据的角度来看我认为是没必要的(但是类也许还是需要一个专门的类,毕竟类是处理写操作的)
随着数据库对json的支持加强(其实不支持也可以),方案四应运而生,这里有点违背设计范式:将整个对象序列化为json然后存入数据库的一个json类型字段(其实text也可以),这样做的缺点是查询的时候稍稍麻烦点