JPA 2.0: исключение выражения TYPE

У меня есть структура наследования с классами, скажем, Parent (в качестве корневого класса) и Child в качестве подкласса.

Так что с JPA 2.0 нет, я могу выбрать только родительский класс с помощью

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

Это только должно возвращать записи Родителя, а не также записи ребенка.

Но с моими EclipseLink 2.1.1 и MySql на Glassfish v3 я всегда получаю следующую ошибку:

"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 вручную. Я думаю, все это делается автоматически при развертывании.

Есть ли что-то, что я должен добавить к своему классу Parent /Child (аннотации т.е.), чтобы объявить структуру наследования? (Но я думаю, что в этом нет необходимости, потому что наследование объявлено Java, не так ли?)

РЕДАКТИРОВАТЬ:
Один важный аспект, который я не упомянул, заключается в том, что я использую метод наследования "TABLE_PER_CLASS".

2 ответа

Решение

Забудь, что я сказал раньше. Это будет работать для 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) выглядит следующим образом:

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.

Решение от Jum Tough не работает для меня. Но проблема доступна только в сочетании с методом наследования "TABLE_PER_CLASS" со всеми другими стратегиями наследования, выражение типа работает просто отлично.

Я думаю, что это ошибка в EclipseLink, потому что я не могу найти ничего в спецификациях JPA 2, исключая из которых простоту, говорит, что выражение типа не работает с TABLE_PER_CLASS.

Gerry

Другие вопросы по тегам