2010-12-01 52 views
2

我有一個帶類的繼承結構,比方說Parent(作爲根類)和Child作爲子類。JPA 2.0:TYPE表達式異常

因此,與JPA 2.0沒有我可以用

SELECT p FROM Parent p WHERE TYPE(p) = Parent 

這隻應該回到父母的條目,也沒有孩子的條目只選擇父類。

但隨着我的EclipseLink 2.1.1和MySQL在Glassfish的第三版時,我總是得到以下錯誤:

"Invalid Type Expression on [my.domain.Parent]. The class 
does not have a descriptor, or a descriptor that does not use 
inheritance or uses a ClassExctractor for inheritance". 

此外,我的手沒有定義ORM映射。這一切都是在部署時自動完成的,我想。

有什麼我必須添加到我的父/子類(註釋,即)來聲明繼承結構? (但我認爲這不應該是必要的,因爲繼承是Java的聲明,是嗎?)

編輯:
我沒有提到的一個重要方面是,我使用的繼承方法「TABLE_PER_CLASS」。

+0

http://www.oracle.com/technetwork/articles/marx-jpa-087268.html此鏈接已話題中提到,使用`移植的繼承映射Strategies`說'即使你的JPA提供者實現可選的「每個具體類的表」繼承映射策略,如果您需要JPA提供程序的可移植性,最好避免這種情況。並且希望使用單一繼承。 – Ramsharan 2013-07-16 09:39:32

回答

4

忘記我之前說過的話。這會爲SINGLE_TABLE戰略合作:

@Entity 
@Table(name="PERSON") 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="GENDER", discriminatorType=DiscriminatorType.STRING, length=6) 
public abstract class Person implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @SequenceGenerator(name="PERSON_PERSONID_GENERATOR", sequenceName="PERSON_ID_SEQ") 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="PERSON_PERSONID_GENERATOR") 
    @Column(name="PERSON_ID", updatable=false, unique=true, nullable=false, precision=22) 
    private long personId; 

    @Column(nullable=false, length=32) 
    private String surname; 

    @Column(name="GIVEN_NAME", nullable=false, length=32) 
    private String givenName; 

    // ... 
} 


@Entity 
@DiscriminatorValue("FEMALE") 
public class Daughter extends Person implements Serializable { 

    @Column(name="NUMBER_OF_DOLLS", precision=22) 
    private int numberOfDolls; 

    // ... 
} 


@Entity 
@DiscriminatorValue("MALE") 
public class Son extends Person implements Serializable { 

    @Column(name="NUMBER_OF_TOY_CARS", precision=22) 
    private Integer numberOfToyCars; 

    // ... 
} 


// JUnit test method 
public void testInheritance() { 
    EntityManager em = createNewEntityManagerInstance(); 

    EntityTransaction tx = em.getTransaction(); 
    tx.begin(); 
    Daughter d = new Daughter(); 
    d.setGivenName("Sue"); 
    d.setSurname("Smith"); 
    d.setNumberOfDolls(5); 
    em.persist(d); 
    Son s = new Son(); 
    s.setGivenName("Joe"); 
    s.setSurname("Smith"); 
    s.setNumberOfToyCars(8); 
    em.persist(s); 
    tx.commit(); 

    Query q; 
    List<?> personList; 
    Person p; 

    q = em.createQuery("SELECT p FROM Person p WHERE TYPE(p) = Daughter"); 
    personList = q.getResultList(); 
    assertEquals(1, personList.size()); 
    p = (Person)personList.get(0); 
    System.out.println(
     "This Daughter is: " + p.getGivenName() + " " + p.getSurname()); 
    q = em.createQuery("SELECT p FROM Person p WHERE TYPE(p) = Son"); 
    personList = q.getResultList(); 
    assertEquals(1, personList.size()); 
    p = (Person)personList.get(0); 
    System.out.println(
     "This Son is: " + p.getGivenName() + " " + p.getSurname()); 
    q = em.createQuery("SELECT p FROM Person p"); 
    personList = q.getResultList(); 
    assertEquals(2, personList.size()); 
    for (Object o : personList) { 
     assertTrue(o instanceof Person); 
     p = (Person)o; 
     System.out.println(
      "This person is: " + p.getGivenName() + " " + p.getSurname()); 
    } 
    em.close(); 
} 

數據庫(我使用的是Oracle)DDL看起來是這樣的:

CREATE TABLE "DEV"."PERSON" 
( 
"PERSON_ID" NUMBER NOT NULL ENABLE, 
"GIVEN_NAME" VARCHAR2(32 BYTE) NOT NULL ENABLE, 
"SURNAME" VARCHAR2(32 BYTE) NOT NULL ENABLE, 
"GENDER" VARCHAR2(6 BYTE) NOT NULL ENABLE, 
"NUMBER_OF_DOLLS" NUMBER, 
"NUMBER_OF_TOY_CARS" NUMBER, 
CONSTRAINT "PERSON_PK" PRIMARY KEY ("PERSON_ID") 
); 

現在你說你正在嘗試使用TABLE_PER_CLASS策略。我無法幫到你,因爲JPA 2.0規範說廠商不需要支持它。您的實現可能不會通過JPA接口正確支持它。

0

Jum Tough的解決方案對我無效。但是,只有在繼承方法「TABLE_PER_CLASS」結合使用所有其他繼承策略時,該問題纔可用,類型表達式工作得很好。

我認爲這是EclipseLink中的一個錯誤,因爲我無法在JPA 2規範中發現任何明確排除的內容,說該類型表達式不適用於TABLE_PER_CLASS。

格里