Hibernate JPA實體繼承的映射(一) 概述


注:文章中據說的實體指的是被@Entity注解的類。

JPA中對象關系映射通常情況下是一個實體對應一個表,兩個實體之間沒有任何關系。如果兩個實體之間是繼承關系,那么該如何映射呢?

JPA中的實體支持繼承映射,多態關聯,多態查詢。抽象類和具體的類都可以是實體,且都可以使用@Entity來注解,映射成實體,並查詢封裝成一個實體。實體類可以繼承非實體類,非實體類也可以繼承實體類。

JPA的繼承映射有如下幾種情況:

一、實體類繼承抽象(具體)實體類

抽象類可以指定成為一個實體,抽象實體和具體實體的唯一區別只是抽象實體不能夠被直接實例化。抽象實體能夠被映射成一個實體並能夠作為查詢目標。

抽象實體類使用@Entity注解或在XML描述符表示成一個實體。

這種映射相對復雜,后面會專門寫一篇文章來舉例說明。這里就不再多說。

二、實體類繼承映射超類(Mapped Superclasses)

實體可以繼承自一個超類,這個超類提供了持久化實體狀態(即屬性或字段)和映射信息,但它本身不是一個實體。通常情況下,這種超類映射的的目的是定義多個實體共有的狀態和映射信息。

映射超類和實體不一樣,它不能夠被查詢,所以不能作為參數傳遞給EntityManager或Query 接口進行操作。映射超類定義的持久化關系必須是單向的。

抽象類或具體的類都可以作為映射超類,使用@MappedSuperclass注解(或mapped-superclass XML描述符元素)來指定映射超類。

映射超類不會生成單獨的表,它的映射信息作用於繼承自它的實體類。

映射超類能夠像實體類一樣被映射,只是它的映射將作用於繼承自它的實體類,因為它本身不存在單獨的表。當作用於子類時,繼承的映射信息將作用於子類對應的表上。子類可以通過@AttributeOverride和AssociationOverride注解或對應的XML描述符元素來覆蓋映射超類的映射信息。下面來看一個實例:

package com.mikan;

import java.io.Serializable; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.MappedSuperclass; @MappedSuperclass public class Employee implements Serializable {  private static final long serialVersionUID = -7674269980281525370L;   @Id  @GeneratedValue(strategy = GenerationType.IDENTITY)  protected Integer empId;   @Column  protected String name;  // getter/setter方法  } package com.mikan; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "FT_EMP") public class FullTimeEmployee extends Employee {  private static final long serialVersionUID = 9115429216382631425L;  // 繼承映射超類的empId和name屬性  @Column  private Double salary;  // getter/setter方法  } package com.mikan; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "PT_EMP") public class PartTimeEmployee extends Employee {  private static final long serialVersionUID = -6122347374515830424L;  // 繼承映射超類的empId和name屬性  @Column(name = "hourly_wage")  private Float hourlyWage;  // getter/setter方法  }

其中Employee是映射超類,它包括兩個字段(即上面所說的狀態)和相應的映射信息,只是這些映射信息都由子類實體FullTimeEmployee和PartTimeEmployee繼承,它本身不會生成對應的表。只會生成FT_EMP和PT_EMP兩個表,這兩個表中的字段包括了子類本身的字段和從映射超類中繼承的字段。即FT_EMP表的字段為:empId、name、salary,而PT_EMP表的字段為:empId、name、hourly_wage。

三、實體類繼承非實體類

一個實體類可以繼承一個非實體超類,這個非實體超類可以是具體的類,也可以是抽象類。

這個非實體超類僅被作為一種繼承行為,它的狀態不會被持久化。所有繼承自非實體超類的狀態(即屬性或字段)在實體子類中都不會被持久化,實體管理器不會管理這些狀態。非實體超類上的所有注解都會被忽略。非實體超類不能作為參數傳遞給EntityManager或Query 接口進行操作。

下面來看一個實例:

public class Cart {  protected Integer operationCount; // transient state  public Cart() {   operationCount = 0;  }  public Integer getOperationCount() {   return operationCount;  }  public void incrementOperationCount() {   operationCount++;  } } @Entity public class ShoppingCart extends Cart {  Collection<Item> items = new Vector<Item>();  public ShoppingCart() {   super();  }  @OneToMany  public Collection<Item> getItems() {   return items;  }  public void addItem(Item item) {   items.add(item);   incrementOperationCount();  } }

ShoppingCart對應的表中不會包含operationCount字段。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM