【问题标题】:JPA 2.0: TYPE expression exceptionJPA 2.0:TYPE 表达式异常
【发布时间】:2011-05-18 14:18:59
【问题描述】:

我有一个 to 类的继承结构,假设 Parent(作为根类)和 Child 作为子类。

所以在 JPA 2.0 中,我只能通过使用来选择父类

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

这应该只返回 Parent 的条目,而不是 child 的条目。

但是在 Glassfish v3 上使用 EclipseLink 2.1.1 和 MySql,我总是收到以下错误:

"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-mapping。我认为这一切都是在部署时自动完成的。

我必须在我的 Parent /Child 类中添加一些东西(即注释)来声明继承结构吗? (但我认为这应该没有必要,因为继承是由Java声明的,是吗?)

编辑:
我没有提到的一个重要方面是我使用了继承方法“TABLE_PER_CLASS”。

【问题讨论】:

  • 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. 并倾向于使用单继承。

标签: java inheritance jpa-2.0 jpql


【解决方案1】:

忘记我之前说过的话。这适用于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 接口正确支持它。

【讨论】:

    【解决方案2】:

    Jum Tough 的解决方案对我不起作用。但是这个问题只有结合继承方法“TABLE_PER_CLASS”和所有其他继承策略才能解决,类型表达式工作得很好。

    我认为这是 EclipseLink 中的一个错误,因为我在 JPA 2 规范中找不到任何明确排除类型表达式不适用于 TABLE_PER_CLASS 的内容。

    格里

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-27
      • 1970-01-01
      • 2011-10-18
      • 2014-10-19
      • 2013-07-01
      • 2019-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多