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

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

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

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

Это должно возвращать только записи 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". 

Кроме того, я не определяю отображение формы вручную. Думаю, все это делается автоматически при развертывании.

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

EDIT:
Один важный аспект, о котором я не упомянул, заключается в том, что я использую метод наследования "TABLE_PER_CLASS".


person gerry    schedule 01.12.2010    source источник
comment
oracle.com/technetwork/articles/marx-jpa-087268.html Эта ссылка упомянула в теме Use Portable Inheritance Mapping Strategies, что Even if your JPA provider does implement the optional “table per concrete class” inheritance mapping strategy, it is best to avoid this if you need JPA provider portability. предпочла использовать одиночное наследование.   -  person Ramsharan    schedule 16.07.2013


Ответы (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) 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.

person Jim Tough    schedule 02.12.2010

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

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

Джерри

person gerry    schedule 02.12.2010