2010-12-01 68 views
2

J'ai une structure d'héritage avec des classes, disons Parent (comme la classe racine) et Child comme sous-classe.JPA 2.0: exception d'expression TYPE

Donc, avec JPA 2.0 Non je ne peux sélectionner que la classe parent en utilisant

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

Cela devrait retourner uniquement les entrées de parent et non aussi les entrées de l'enfant.

Mais avec mon EclipseLink 2.1.1 et MySql sur Glassfish v3, je reçois toujours l'erreur suivante:

"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". 

De plus, je ne définissent ORM-mapping à la main. Tout cela est fait automatiquement lors du déploiement, je pense.

Y a-t-il quelque chose que je dois ajouter à ma classe Parent/Enfant (une annotation, par exemple) pour déclarer la structure d'héritage? (Mais je pense que cela ne devrait pas être nécessaire, parce que l'héritage est déclarée par Java, est-il?)

EDIT:
Un aspect important que je l'ai mentionné ne pas que j'utilise le méthode d'héritage "TABLE_PER_CLASS".

+0

http://www.oracle.com/technetwork/articles/marx-jpa-087268.html Ce lien a mentionné dans le sujet 'Utilisons Mapping d'héritage Portable Strategies' que' Même si votre fournisseur JPA ne implémentez la stratégie de mappage d'héritage facultatif "table par classe concrète", il est préférable d'éviter cela si vous avez besoin de la portabilité du fournisseur JPA. »et a préféré utiliser l'héritage unique. – Ramsharan

Répondre

4

Oubliez ce que j'ai déjà dit. Cela fonctionne pour SINGLE_TABLE stratégie:

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

La base de données (j'utilise Oracle) LDD ressemble à ceci:

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") 
); 

Maintenant, vous avez dit que vous essayez d'utiliser la stratégie TABLE_PER_CLASS. Je ne peux pas vous aider là-bas, puisque la spécification JPA 2.0 dit que les fournisseurs ne sont pas tenus de le prendre en charge. Votre implémentation peut ne pas le prendre en charge correctement via les interfaces JPA.

0

la solution de Jum Tough ne fonctionne pas pour moi. Mais le problème est seulement disponible en combinaison avec la méthode d'héritage "TABLE_PER_CLASS" avec toutes les autres stratégies d'héritage que l'expression de type fonctionne très bien.

Je pense qu'il s'agit d'un bogue dans EclipseLink, car je ne trouve rien dans les spécifications de JPA 2 qui explicite exclues dit que l'expression de type ne fonctionne pas avec TABLE_PER_CLASS.

Gerry