繼承是java的三大特性之一,這是衆所周知的。在真實的開發環境中也運用的很多,比如說BaseDao,BaseAction。但是本文所要讨論的并不是這些,而是關于Entity的繼承。就目前自己接觸到的項目而言,Entity使用繼承的比較少。但是在hibernate中,提供了關于Entity繼承的内容,本文就簡單的介紹一下。
Java代碼側,繼承唯一的實作手段是使用關鍵字extends,而且不能多繼承。在資料庫一側實作繼承的話,實作繼承的表結構有多種,Hibernate介紹了三種,分别是SINGLE_TABLE,TABLE_PER_CLASS,JOINED.這裡介紹SINGLE_TABLE,JOINED。
現有三個類:Person(id,name),Student(id,name,score),Teacher(id,name,title)
在Java側,Student和Teacher都從Person繼承。
資料庫側
1.SINGLE_TABLE(單一表)用一張表來描述着三個Entity,那麼就需要使用一個Flag Column 來區分該條記錄是People,Student,Teacher。建好的表結構如下P_S_T(id,name,score,title,flg)。
flag=0,Person類,score和title字段都沒有資料;
flag=1,Student類,score字段有資料,title字段沒資料;
flag=2,Teacher類,score字段沒資料,title字段有資料。
SINGLE_TABLE 方式Annotation實作
Person Entity
package com.bjsxt.hibernate;
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;
/**
*@Inheritance指定繼承政策
*@DiscriminatorColumn 标志字段定義
*@DiscriminatorValue ,當資料為Person類時候,flg=0
*/
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="flg", discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("0")
public class Person {
private int id;
private String name;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Student Entity
package com.bjsxt.hibernate;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
/**
**@DiscriminatorValue ,當資料為Student類時候,flg=1
*/
@Entity
@DiscriminatorValue("1")
public class Student extends Person {
private int score;
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}
Teacher Entity
package com.bjsxt.hibernate;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
/**
**@DiscriminatorValue ,當資料為Teacher類時候,flg=2
*/
@Entity
@DiscriminatorValue("2")
public class Teacher extends Person {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
-
JOINED 使用外鍵連接配接的方式實作繼承
三張表分别如下
Person(id,name);
Student(id,score),id 參照Person的id
Teacher(id,title),id 參照Person的id。
JOINED 方式Annotation實作
Person Entity
package com.bjsxt.hibernate;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {
private int id;
private String name;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Student Entity
package com.bjsxt.hibernate;
import javax.persistence.Entity;
@Entity
public class Student extends Person {
private int score;
public int getScore() {
return score;
} //Person p = Person(load(1));
public void setScore(int score) {
this.score = score;
}
}
Teacher Entity
package com.bjsxt.hibernate;
import javax.persistence.Entity;
@Entity
public class Teacher extends Person {
private String title;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
以上是SINGLE_TABLE和JOINED的使用。
二者的比較:SINGLE_TABLE 隻有一張表很友善,但是可能會造成大量的資料備援,很多字段都是空的。JOINED方式雖然表多,但是邏輯是很清楚的。關于二者的使用,具體情況具體分析。