英文原址
網上這個主題的文章不在少數,這個系列的文章的部分價值在于給出了注解模式(Annotation)的例子。文章易懂,權當增強記憶,捎帶着練習下翻譯(翻譯不當之處請指出)。
Hibernate中繼承關系的簡介:
java是一種面向對象語言,它可以實作繼承關系。然而,繼承卻是"對象模型-關系模型"不比對的最顯而易見的方面之一。面向對象系統能夠輕松的對“is a”和“has a”關系進行模組化。而關系模型隻能表達兩個實體間的"has a"關系。hibernate能夠把有關聯的表映射為對象,但你需要根據需要來選擇不同的映射政策。
Hibernate繼承關系映射政策分為三種:一張表對應一整棵類繼承樹、一個類對應一張表、每一個具體類對應一張表。
之一:一張表對應一整棵類繼承樹(子類和父類共享同一張表)假設我們有一個 Person 類及其子類 Employee. 每個類包括如下屬性:
* class Person
- firstname
- lastname
* class Employee
- joining_date
- department_name
在“一張表對應一整棵類繼承樹”這種模式中,繼承樹上的所有類的資料都存儲在一張表上,鑒别器字段(discriminator )是唯一的辨別每個類的關鍵字段。
下面是“一張表對應一整棵類繼承樹”模式的優點和缺點:
優點
這種模式提供了最好的性能,因為即使在深層繼承的情況下,檢索一條子類資料,也隻需要一次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 時,指定鑒别器列。 此注解隻能用于兩種類:一、繼承樹的根類,二、繼承樹的某子類,并且該子類定義了自己繼承政策。
如果在需要鑒别器列的時候,沒有使用@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”将被置入鑒别器列。
MainClasspackage 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')
需要例子中完整代碼的,原文連接配接中提供有下載下傳。
版權聲明:本文為CSDN部落客「weixin_33922670」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。
原文連結:https://blog.csdn.net/weixin_33922670/article/details/91804932