英文原址html
网上这个主题的文章不在少数,这个系列的文章的部分价值在于给出了注解模式(Annotation)的例子。文章易懂,权当加强记忆,捎带着练习下翻译(翻译不当之处请指出)。 java
Hibernate中继承关系的简介:sql
java是一种面向对象语言,它能够实现继承关系。然而,继承倒是"对象模型-关系模型"不匹配的最显而易见的方面之一。面向对象系统可以轻松的对“is a”和“has a”关系进行建模。而关系模型只能表达两个实体间的"has a"关系。hibernate可以把有关联的表映射为对象,但你须要根据须要来选择不一样的映射策略。数据库
Hibernate继承关系映射策略分为三种:一张表对应一整棵类继承树、一个类对应一张表、每个具体类对应一张表。session
之一:一张表对应一整棵类继承树(子类和父类共享同一张表)app
假设咱们有一个 Person 类及其子类 Employee. 每一个类包括以下属性:性能
* class Person - firstname - lastname * class Employee - joining_date - department_name
在“一张表对应一整棵类继承树”这种模式中,继承树上的全部类的数据都存储在一张表上,鉴别器字段(discriminator )是惟一的标识每一个类的关键字段。spa
下面是“一张表对应一整棵类继承树”模式的优势和缺点:.net
优势hibernate
这种模式提供了最好的性能,由于即便在深层继承的状况下,检索一条子类数据,也只须要一次select操做。
缺点
对于任何一个子类的变动,好比增删改某字段,都将致使数据库表的变动。
建表语句
CREATE TABLE `person` ( `person_id` BIGINT(10) NOT NULL AUTO_INCREMENT, `firstname` VARCHAR(50) NULL DEFAULT NULL, `lastname` VARCHAR(50) NULL DEFAULT NULL, `joining_date` DATE NULL DEFAULT NULL, `department_name` VARCHAR(50) NULL DEFAULT NULL, `discriminator` VARCHAR(20) NOT NULL, PRIMARY KEY (`person_id`) )
PERSON表被用来同时存储 Employee 和 Person 对象.
Hibernate 继承: XML 映射
下面的例子展现了如何用XML方式映射 Employee 和 Person 实体类.
Person.java
package net.viralpatel.hibernate; public class Person { private Long personId; private String firstname; private String lastname; // Constructors and Getter/Setter methods, }
Employee.java
package net.viralpatel.hibernate; import java.util.Date; public class Employee extends Person { private Date joiningDate; private String departmentName; // Constructors and Getter/Setter methods, }
Person.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="net.viralpatel.hibernate"> <class name="Person" table="PERSON" discriminator-value="P"> <id name="personId" column="PERSON_ID"> <generator class="native" /> </id> <discriminator column="DISCRIMINATOR" type="string" /> <property name="firstname" /> <property name="lastname" column="lastname" /> <subclass name="Employee" extends="Person" discriminator-value="E"> <property name="departmentName" column="department_name" /> <property name="joiningDate" type="date" column="joining_date" /> </subclass> </class> </hibernate-mapping>
注意这里只定义了一个 hibernate 映射文件 Person.hbm.xml.
Person 和 Employee 类都定义在这同一个文件中.
<discriminator> 标签用来指定鉴别器列,包括列名和类型.
<subclass> 标签用于映射子类 Employee. 注意咱们没有用常规的 <class>标签来映射 Employee ,由于它位于继承关系树下端。
Person 类的鉴别器的值被指定为 “P” ,相应的 Employee 是“E”,这样, 当Hibernate将要持久化person 或 employee时,相应的“P”或“E”将被置入鉴别器字段。
Hibernate 继承: 注解映射
下面的例子展现了如何用JPA注解方式来映射 Employee 和 Person 实体类。
Person.java
package net.viralpatel.hibernate; import javax.persistence.Column; import javax.persistence.DiscriminatorColumn; import javax.persistence.DiscriminatorType; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.Table; @Entity @Table(name = "PERSON") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn( name="discriminator", discriminatorType=DiscriminatorType.STRING ) @DiscriminatorValue(value="P") public class Person { @Id @GeneratedValue @Column(name = "PERSON_ID") private Long personId; @Column(name = "FIRSTNAME") private String firstname; @Column(name = "LASTNAME") private String lastname; // Constructors and Getter/Setter methods, }
Person 类是继承树的根类,因此咱们使用了下面一些注解使其成为根类。
@Inheritance – 定义一个实体类继承树的继承策略,这个注解只能定义在继承树的根类上。
@DiscriminatorColumn – 用于当@Inheritance 的值被定义为 SINGLE_TABLE 或 JOINED 时,指定鉴别器列。 此注解只能用于两种类:1、继承树的根类,2、继承树的某子类,而且该子类定义了本身继承策略。
若是在须要鉴别器列的时候,没有使用@DiscriminatorColumn注解,那么鉴别器列的名称将默认为“DTYPE”,类型将默认为“STRING”。
@DiscriminatorValue – 用于指定给定实体类所对应的鉴别器列的具体值。 DiscriminatorValue 注解只能用在具体的实体类中。若是使用了鉴别器列,可是没有使用 DiscriminatorValue 注解,一个鉴别器值生成器将生效并产生一个鉴别器值来表明这个类。若是鉴别器列的类型是 STRING, 鉴别器列的值默认是该类的名称。若是不采用默认值,那么应该在继承树的每一个类中都使用该注解。
Employee.java
package net.viralpatel.hibernate; import java.util.Date; import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name="PERSON") @DiscriminatorValue("E") public class Employee extends Person { @Column(name="joining_date") private Date joiningDate; @Column(name="department_name") private String departmentName; // Constructors and Getter/Setter methods, }
Employee类是Person类的子类,因此在映射时,使用@DiscriminatorValue注解来定义鉴别器的值,此例中,“E”将被置入鉴别器列。
MainClass
package net.viralpatel.hibernate;
import java.util.Date; import org.hibernate.Session; import org.hibernate.SessionFactory; public class Main { public static void main(String[] args) { SessionFactory sf = HibernateUtil.getSessionFactory(); Session session = sf.openSession(); session.beginTransaction(); Person person = new Person("Steve", "Balmer"); session.save(person); Employee employee = new Employee("James", "Gosling", "Marketing", new Date()); session.save(employee); session.getTransaction().commit(); session.close(); } }
Main class 用来持久化 Person 和 Employee类的实例。注意两个类都存储在PERSON表中,鉴别器列用于区分两个实体。
输出结果
Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, discriminator) values (?, ?, 'P') Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, department_name, joining_date, discriminator) values (?, ?, ?, ?, 'E')
须要例子中完整代码的,原文链接中提供有下载。