ch03 继承关系映射
如何建表,保持Java中的父子类继承关系–映射起作用
范例:
一、每个具体类对应一张表
1.建表
具体类,即子类,
如父类不需要持久化,那么不为父类建表
HourlyEmployee
id | name | rate |
---|---|---|
SalaryEmployee
id | name | salary |
---|---|---|
2.缺点
子类较多、公共属性较多时每张表会存在很多重复字段
这种方式相当于多个单实体映射,未体现多态
3.映射文件
每个具体类建一个映射文件
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q9fcUihc-1646566955992)(C:\Users\86183\AppData\Roaming\Typora\typora-user-images\image-20220228201541338.png)]
4.使用注解
具体类照常
@Entity
@Table(name = "hourly_emloyee")
public class HourlyEmployee extends Employee {
@Column(name = "rate")
private double rate;
}
未建表的父类添加@MapperedSuperClass
@MappedSuperclass
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
//属性名和表中字段名相同时可以省略column注解,映射文件的column元素也是同样道理
private String name;
}
二、每个类层次对应一张表
1.建表
它们都属于一类,用一张表来表示,添加一个字段作为区分标志
employee
id | name | employee_type | rate | salary |
---|---|---|---|---|
2.好处
支持**多态查询,**就是从数据库中检索父类对象时,同时包含所有子类的对象
3.映射文件
<class name="Employee" table="EMPLOYEE">
<id name="id">
<generator class="increment"/>
</id>
<discriminator column="EMPLOYEETYPE" />
<property name="name"/>
<subclass name="HourlyEmployees" discriminator-value="HE">
<property name="rate"/>
</subclass>
<subclass name="SalariedEmployees" discriminator-value="SE">
<property name="salary"/>
</subclass>
</class>
1.discriminator:区分标志,不在实体类中出现,只在表中出现,
2.subclass:映射子类
必须紧跟id元素
2.如果 父类本身也需要被持久化,可以在元素中设置 discriminator-value 属性的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qU0kfqL6-1646566955993)(C:\Users\86183\AppData\Roaming\Typora\typora-user-images\image-20220228203043981.png)]
4.多态查询
一次查询可以查出所有子类对象
// 多态查询--通过一次查询能够得到所有子类的对象,是哪个子类就映射为那个子类对象
public static void findEmployee() {
// 1.获取Session对象
Session session = HibernateUtil.openSession();
// 2.创建查询对象,使用hql
String queryHql = "from Employee ";
Query query = session.createQuery(queryHql);
// 3.执行查询
List list = query.list();// 包含多条--list;唯一--
System.out.println(list);
}
5.使用注解
5.1父类
@Entity
@Table(name="employee")
//继承关系的生成策略
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)//总共一张表
//映射额外字段
@DiscriminatorColumn(name="employee_type")
public class Employee {
@Id
@GeneratedValue(strategy=GenerationType.IDENTI TY)
private Integer id;
private String name;
}
5.2子类
@Entity
@DiscriminatorValue(value="HE")
public class HourlyEmployee extends Employee{
private double rate;
}
注意:
- 只有父类上标注@Table,因为只有这一个表
- 注意区分标志:父类标注字段名,子类标注字段值
三、每个类对应一张表
1.建表
employee
id | name |
---|---|
hourly_employee
id | rate |
---|---|
salary_employee
id | salary |
---|---|
2.映射文件
一个映射文件管理三张表
<class name="Employee" table="EMPLOYEE">
<id name="id">
<generator class="increment"/>
</id>
<property name="name"/>
<joined-subclass name="HourlyEmployee" table="HOURLYEMPLOYEE">
<key column="EMPLOYEEID"/>
<property name="rate"/>
</joined-subclass>
<joined-subclass name="SalariedEmployee"
table="SALARIEDEMPLOYEE">
<key column="EMPLOYEEID"/>
<property name="salary"/>
</joined-subclass>
</class>
(1)joined-subclass:标识子类
(2)key:子类的主键
3.使用注解
@Entity、@Table都有
3.1父类:
指定继承关系的生成策略。
@Inheritance(strategy=InheritanceType.JOINED)
3.2子类:
指定子类对应表的主键列。
@PrimaryKeyJoinColumn(name="EMPLOYEEID")
既是主键又是外键
不涉及生成策略
四、三种方式的对比
1.实体类一模一样,数据库表不同,映射文件不同
关系数据模型的复杂度 | 查询性能 | DB的可维护性 | 是否支持多态查询 | |
---|---|---|---|---|
每个具体类一张表 | 每个具体类中包含重复字段 | 如果查父类,就得查所有具体子类的表 | 若父类属性发生变化,须修改所有子类对应的表 | × |
一个大类一张表 | 优:只需创建一个表 缺:表中需额外引入区分子类类型的字段 | 好 | 只需修改一张表 | √ |
一个类一张表 | 表的数目多,且表之间存在外键参照关系 | 需要连接查询 | 某个类属性发生变化,只需修改该类对应的表 | √ |