首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> JSP 程式設計 >> 關於JSP

EJB 3.0 實體 Bean 繼承映射策略:單表策略完整指南

     編輯:關於JSP

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 { ... }

完整實體類別

父實體 Person.java

@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
}

子實體 Man.java

@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; }
}

子實體 Woman.java

@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; }
}

會話 Bean 與查詢

@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 自動返回具體子類實例
  • 單表策略查詢效能最佳,但稀疏欄位較多時浪費空間
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved