在面向对象的程序领域中,类与类之间是有继承关系的,例如Java世界中只需要extends关键字就可以确定这两个类的父子关系,但是在关系数据库中,有的知识关联关系。为了将继承映射到关系数据库中,Hibernate提供了3中方式
- 整个的继承体系就用一张表(single_table)注解:@Inheritance(strategy =InheritanceType.SINGLE_TABLE)
- 每个类一张表,子类存放所特有的属。性注解:@Inheritance(strategy= InheritanceType.JOINED)
- 每个具体类一张表,子类所特有的属性。对应注解:注解为:@Inheritance(strategy =InheritanceType.TABLE_PER_CLASS)
在 Annotation中使用的是@inheritance注解,并且要使用strategy策略指定方式
具体实例
现在假设有People、student、teacher三个类,
1·单表
该种方式SINGLE_TABLE是将父类和其所有的子类集合在一块,存在一张表中,并创建一个新的字段来判断对象的类型。
通过@Enitty引入实体
@Table(name="表名")
@colum列名称
@Entity
@Table(name = "People")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "emp_type")
public class People implements Serializable {
private static final long serialVersionUID = -7674269980281525370L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer Id;
@Column
protected String name;
// getter/setter方法
}
学生实体
@Entity
@DiscriminatorValue("ES") //辨别字段
public class Student extends People {
private static final long serialVersionUID = 9115429216382631425L;
@Column
private int className;
// getter/setter方法
}
教师实体
@Entity
@DiscriminatorValue("PT")
public class Teacher extends People{
private static final long serialVersionUID = -6122347374515830424L;
@Column(name = "hourly_wage")
private Double salary
// getter/setter方法
}
上面的例子中,只会生成一个表,包含了字段emp_type、Id、name、salary、className。当保存student时,emp_type的值为“ST”,当保存Teacehere时,emp_type的值为"PT"。
2·每个子类一张表,存放自己特有特性。
这种策略超类会被映射成一个单独的表,每个子类也会映射成一个单独的表。子类对应的表中只包括自身属性对应的字段,默认情况下使用主键作为超类对应的表的外键(同时也值主键,称为唯一外键)。
会将超类也生成一张表,少了辨别字段。
基本的写法如下:
@Entity
@Table(name = "People")
@Inheritance(strategy = InheritanceType.JOINED)//重点策略的不同
public class People implements Serializable {
private static final long serialVersionUID = -7674269980281525370L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer Id;
@Column
protected String name;
// getter/setter方法
}
学生实体
@Entity
@Table(name = "Student")
public class Student extends People {
private static final long serialVersionUID = 9115429216382631425L;
@Column
private int className;
// getter/setter方法
}
教师实体
@Entity
@Table(name = "Teacher")
public class Teacher extends People{
private static final long serialVersionUID = -6122347374515830424L;
@Column(name = "hourly_wage")
private Double salary
// getter/setter方法
}
这种映生成第三章表,分别是People,Student,Teacher, people 中为共有字段, stuent,Teacher为给自特有字段,同时
People中的主键id作为Student,Teacher的外键,同时也是主键存在。子类保存一条数据,会在people中插入一条记录,然后在子类表中再插入数据。
3·每个具体类一个表
这种映射策略每个具体类都会映射成一个单独的表,类的所有属性,包括继承的属性都会映射成表的列
具体实例我们看父类
@Entity
@Table(name = "People")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class People implements Serializable {//抽象类
private static final long serialVersionUID = -7674269980281525370L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer Id;
@Column
protected String name;
// getter/setter方法
}
父类的abstract特性是不映射为具体的一个表的。
小结:
以上为JPA的Hibernate继承映射的实现。与Hibernater的配置相比简单的很多,但是灵活性却少了很多,同时该配置的通用性却大大提高了。