EJB 3.0 支援實體 Bean 繼承映射,提供三種策略。本文詳細講解最常用的單表策略:父子實體共用一張表,透過鑑別器欄位區分實體類型。
| 策略 | 註解值 | 特點 |
|---|---|---|
| 單表策略 | SINGLE_TABLE | 所有類共用一表,需鑑別欄位,查詢效能最好 |
| 聯表策略 | JOINED | 各類各表,透過主鍵聯結,正規化程度高 |
| 每類一表 | TABLE_PER_CLASS | 每個具體類一表,無共用表,多型查詢需 UNION |
@Entity
@Inheritance(
strategy = InheritanceType.SINGLE_TABLE,
discriminatorType = DiscriminatorType.STRING
)
@DiscriminatorColumn(
name = "P_TYPE", // 鑑別欄位名
nullable = true,
length = 10
)
public class Person implements Serializable { ... }
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE,
discriminatorType = DiscriminatorType.STRING)
@DiscriminatorColumn(name = "P_TYPE", nullable = true)
public class Person implements Serializable {
private int id;
private String name;
private String gender;
@Id @GeneratedValue(strategy = GenerationType.AUTO)
public int getId() { return id; }
// ... name, gender getter/setter
}
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE,
discriminatorType = DiscriminatorType.STRING,
discriminatorValue = "Man")
public class Man extends Person {
private boolean isGood;
public boolean isGood() { return isGood; }
public void setGood(boolean isGood) { this.isGood = isGood; }
}
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE,
discriminatorType = DiscriminatorType.STRING,
discriminatorValue = "Woman")
public class Woman extends Person {
private boolean isBeautiful;
public boolean isBeautiful() { return isBeautiful; }
public void setBeautiful(boolean isBeautiful) { this.isBeautiful = isBeautiful; }
}
@Stateless
public class PersonDAOBean implements PersonDAO {
@PersistenceContext EntityManager em;
public int createMan(String name, String gender, boolean good) {
Man m = new Man(); m.setName(name); m.setGender(gender); m.setGood(good);
em.persist(m); return m.getId();
}
public int createWoman(String name, String gender, boolean beautiful) {
Woman w = new Woman(); w.setName(name); w.setGender(gender); w.setBeautiful(beautiful);
em.persist(w); return w.getId();
}
public Person find(int id) { return em.find(Person.class, id); }
public List<Person> findByName(String name) {
return em.createQuery("FROM Person p WHERE p.name = :name")
.setParameter("name", name).getResultList();
}
public List<Person> findByGender(String gender) {
return em.createQuery("FROM Person p WHERE p.gender = :gender")
.setParameter("gender", gender).getResultList();
}
}
public class Client {
public static void main(String[] args) throws NamingException {
InitialContext ctx = new InitialContext();
PersonDAO dao = (PersonDAO) ctx.lookup(PersonDAO.class.getName());
int id = dao.createMan("晁岳攀", "男", true);
dao.createWoman("朱立煥", "女", true);
Person p = dao.find(id);
System.out.printf("%s的性別:%s%n", p.getName(), p.getGender());
for (Object o : dao.findByName("朱立煥")) {
Woman w = (Woman) o;
System.out.printf("%s漂亮嗎?結論:%b%n", w.getName(), w.isBeautiful());
}
}
}
PERSON 表:
+----+----------+--------+------+--------+------------+
| ID | NAME | GENDER | P_TYPE | IS_GOOD | IS_BEAUTIFUL |
+----+----------+--------+------+--------+------------+
| 1 | 晁岳攀 | 男 | Man | true | NULL |
| 2 | 朱立煥 | 女 | Woman| NULL | true |
+----+----------+--------+------+--------+------------+
@DiscriminatorColumn 定義鑑別欄位,僅用於單表與聯表策略discriminatorValue,值唯一對應實體類型NULL(對應其他類型記錄)FROM Person 自動返回具體子類實例