在学软件工程的时候没有弄明白ER图
和 域模型
的关系。后来才渐渐理解了。ER图
是基于数据库的数据建模,是面向关系的,是has a
的关系(类的组合),而域模型
是面向对象的,既是has a
又是is a
的关系(类的继承)。弄明白了这些之后我们知道在面向关系和对象的世界里继承是一种结构上的不匹配。但是我们如何才能完成继承关系在数据库中的映射呢?
设计思想
首先来介绍一下我们在思想上如何实现呢?
- 每个子类使用一个表:将
is a
(继承)关系表示为has a
(外键)关系,并且使用 SQL JOIN
操作。
- 每个类层次结构使用一个表。
每个类层次结构使用一个表
我们说这种方法是最简单的映射关系了。在这个类层次映射的到的数据表中乎有一个额外的类型识别器或公式的值会标识出特定行所表示的具体子类。
域模型
父类
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Entity @DiscriminatorColumn(name = "table_type") //区分子类的标识符 public class BillingDetails { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @NotNull @Column(nullable = false) private String owner; //getter and setter }
|
BankAccount子类
1 2 3 4 5 6 7 8
| @Entity @DiscriminatorValue("CreditCard") //table_type字段为CreditCard时表示CreditCard类 public class CreditCard extends BillingDetails { protected String cardNumber; protected String expMonth; //gettter and setter }
|
CreditCard子类
1 2 3 4 5 6 7 8
| @Entity @DiscriminatorValue("CreditCard") public class CreditCard extends BillingDetails { protected String account; protected String bankName; //getter and setter }
|
表的结构
SQL查询
以BankAccount
为例
hql
当我们用hql
查询的时候没有什么改动,因为Hinernate
已经为我们自动处理table_type
这个字段来标示不同的子类。
1
| select bankAccount from BankAccount as bankAccount
|
sql
1 2 3 4 5 6
| select ID, OWNER, CARDNUMBER, EXPMONTH from BILLINGDETAILS where TABLE_TYPE='BANKACCOUNT'
|