EJB 3.0 透過 @Inheritance 註解定義實體繼承映射策略:
| 策略 | 註解值 | 資料表結構 | 適用場景 |
|---|---|---|---|
| 單表策略 | SINGLE_TABLE | 父/子實體共用一張表,判別欄位區分類型 | 層次淺、欄位少、查詢效能優先 |
| 連接表策略 | JOINED | 父表存共同欄位,子表存特有欄位,主鍵關聯 | 規範化要求高、子實體差異大 |
| 每類一表 | TABLE_PER_CLASS | 每個實體類獨立一表,含所有欄位(含繼承) | 多態查詢少、獨立演化需求強 |
@Inheritance(
strategy = InheritanceType.SINGLE_TABLE,
discriminatorType = DiscriminatorType.STRING,
discriminatorValue = "PERSON"
)
strategy:三種策略之一,預設 SINGLE_TABLEdiscriminatorType:判別欄位類型(STRING/CHAR/INTEGER)discriminatorValue:當前實體在判別欄的值@DiscriminatorColumn(
name = "P_TYPE",
discriminatorType = DiscriminatorType.STRING,
length = 10,
nullable = true
)
SINGLE_TABLE 與 JOINED 策略@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE, discriminatorType = DiscriminatorType.STRING)
@DiscriminatorColumn(name = "P_TYPE", nullable = true)
@DiscriminatorValue("PERSON")
public class Person implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private String gender;
// getter/setter...
}
@Entity
@DiscriminatorValue("MAN")
public class Man extends Person {
private String beardStyle; // 男性特有屬性
// getter/setter...
}
@Entity
@DiscriminatorValue("WOMAN")
public class Woman extends Person {
private String hairStyle; // 女性特有屬性
// getter/setter...
}
CREATE TABLE PERSON (
ID INT PRIMARY KEY,
NAME VARCHAR(100),
GENDER VARCHAR(10),
BEARD_STYLE VARCHAR(50), -- Man 專用,Woman 為 NULL
HAIR_STYLE VARCHAR(50), -- Woman 專用,Man 為 NULL
P_TYPE VARCHAR(10) NOT NULL -- 判別欄:'PERSON'/'MAN'/'WOMAN'
);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Man man = new Man();
man.setName("Adam");
man.setGender("Male");
man.setBeardStyle("Full");
em.persist(man);
Woman woman = new Woman();
woman.setName("Eve");
woman.setGender("Female");
woman.setHairStyle("Long");
em.persist(woman);
em.getTransaction().commit();
// 查詢驗證
List<Person> all = em.createQuery("SELECT p FROM Person p").getResultList();
FROM Person)且子類欄位少 → SINGLE_TABLE@Embedded / 關聯關係解決的,盡量不用繼承