Hibernate中有以下三种策略将这种关系映射到数据表上:
· 每个类层次结构一个表(table per class hierarchy)
· 每个子类一个表(table per subclass)
· 每个具体类一个表(table per concrete class)(有一些限制)
每个类层次结构一个表的方式是将所有继承同一父类别的对象储存在同一个表格中,为了做到这一点,
需要在表中使用识别字段来表示某一列(row)是属于某个子类别或父类别,在这个主题中我们将先说明这个方法。
一个例子如下:
· 类Animal.java
package com.jason.inheritance;
/**
* @hibernate.class
* table="Animal"
* discriminator-value="Animal"
* @hibernate.discriminator
* column="ANIMAL_TYPE"
* type="string"
* length = "10"
*/
public class Animal {
private Long id;
private String name;
/**
* @hibernate.id
* column="ID"
* generator-class="hilo"
* unsaved-value="null"
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* @hibernate.property
* length = "24"
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void makeSound(){};
}
· 子类Cat.java
package com.jason.inheritance;
public class Cat extends Animal {
privateString FurColor;
publicvoid makeSound() {
System.out.println("喵喵");
}
publicString getFurColor() {
return FurColor;
}
publicvoid setFurColor(String furColor) {
FurColor = furColor;
}
}
· 子类Dog.java
package com.jason.inheritance;
/**
* @hibernate.subclass
* discriminator-value="Dog"
*/
public class Dog extends Animal {
private String category;
public void makeSound() {
System.out.println("汪汪");
}
/**
* @hibernate.property
* length = "24"
*/
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
}
· Animal.hbm.xml
|
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.jason.inheritance.Animal" table="Animal"
dynamic-update="false" dynamic-insert="true" select-before-update="false"
optimistic-lock="version" discriminator-value="Animal">
<id name="id" column="ID" type="java.lang.Long" unsaved-value="null">
<generator class="hilo">
</generator>
</id>
<discriminator column="ANIMAL_TYPE" type="string" length="10"/>
<property name="name" type="java.lang.String" update="true" insert="true"
access="property" column="name" length="24"/>
<subclass name="com.jason.inheritance.Cat" dynamic-update="false"
dynamic-insert="false" discriminator-value="Cat">
<property name="furColor" type="java.lang.String" update="true"
insert="true" access="property" column="furColor" length="24"/>
</subclass>
<subclass name="com.jason.inheritance.Dog" dynamic-update="false"
dynamic-insert="false" discriminator-value="Dog">
<property name="category" type="java.lang.String" update="true"
insert="true" access="property" column="category" length="24"/>
</subclass>
</class>
</hibernate-mapping>
|
显然对应的表是Animal(ID, ANIMAL_TYPE, name, furColor, category)
需要在表中使用识别字段来表示某一列(row)是属于某个子类别或父类别,
就是用ANIMAL_TYPE来表示的!
插入记录的sql如下:
Hibernate: insert into Animal (name, ANIMAL_TYPE, ID) values (?, 'Animal', ?)
Hibernate: insert into Animal (name, furColor, ANIMAL_TYPE, ID) values (?, ?, 'Cat', ?)
Hibernate: insert into Animal (name, category, ANIMAL_TYPE, ID) values (?, ?, 'Dog', ?)
● 优点:
· 实现简单。
· 支持多态——对象角色发生变化,或存在多重角色时。
· 报表操作实现简单:表中包含了所有信息。
● 缺点:
· 增加类层次中的耦合。类层次中任何类的属性的增加都会导致表的变更;某个子类属性的修改会影响到整个层次结构,而不仅仅是该子类。
· 浪费了一些数据库空间。浪费空间的多少取决于继承层次的深度。层次越深,不同的属性越多,属性的全集就越大,也就越浪费空间。
· 要求由子类定义的字段不能有非空(NOT NULL)约束。
参考:
· HIBERNATE - 符合Java习惯的关系数据库持久化(第8章)