Java 为什么我不能用与JPA2.1中的实体类型匹配的TYPE-WHERE子句查询实体?

Java 为什么我不能用与JPA2.1中的实体类型匹配的TYPE-WHERE子句查询实体?,java,hibernate,jpa-2.1,Java,Hibernate,Jpa 2.1,实体类A形式的查询,形式为 SELECT a from A a WHERE TYPE(a) = A 失败 could not resolve property: class of: de.richtercloud.type.operator.nonsense.A [SELECT a from de.richtercloud.type.operator.nonsense.A a WHERE TYPE(a) = A] 我不理解这一点,因为将A限制为A应该排除所有不属于A的超类实例以及子类实例 例

实体类A形式的查询,形式为

SELECT a from A a WHERE TYPE(a) = A
失败

could not resolve property: class of: de.richtercloud.type.operator.nonsense.A [SELECT a from de.richtercloud.type.operator.nonsense.A a WHERE TYPE(a) = A]
我不理解这一点,因为将A限制为A应该排除所有不属于A的超类实例以及子类实例

例如:

package de.richtercloud.type.operator.nonsense;

import java.io.File;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

/**
 * Illustrates the problem/misunderstanding that storing an {@link A} and
 * querying it with a {@code WHERE TYPE([identifier]) = A} fails with
 * {@code org.hibernate.QueryException: could not resolve property:
 * class of: de.richtercloud.type.operator.nonsense.A}.
 * @author richter
 */
public class NewMain {
    private final static File DATABASE_DIR = new File("/tmp/type-operator-nonsense");
    private final static String DERBY_CONNECTION_URL = String.format("jdbc:derby:%s", DATABASE_DIR.getAbsolutePath());

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws SQLException {
        //setup database
        EntityManagerFactory entityManagerFactory = null;
        try {
            Map<Object, Object> entityManagerFactoryMap = new HashMap<>();
            entityManagerFactoryMap.put("javax.persistence.jdbc.url",
                    String.format("%s;create=%s", DERBY_CONNECTION_URL, !DATABASE_DIR.exists()));
            entityManagerFactory = Persistence.createEntityManagerFactory("type-operator-nonsense",
                    entityManagerFactoryMap);

            //show issue
            EntityManager entityManager = entityManagerFactory.createEntityManager();
            A a = new A(1L, "b");
            entityManager.getTransaction().begin();
            entityManager.persist(a);
            entityManager.flush();
            Query query = entityManager.createQuery("SELECT a from A a WHERE TYPE(a) = A");
            List<?> queryResult = query.getResultList();
            entityManager.getTransaction().commit();
            System.out.println(queryResult.size());
        }finally {
            if(entityManagerFactory != null) {
                entityManagerFactory.close();
            }
        }
    }
}
使用org.hibernate:hibernate entitymanager:5.1.0.Final和org.apache.derby:derby:10.11.1.1

在本例中,A是一个不涉及继承的POJO,这对于我所期望的限制并不重要,尽管如果没有继承,应用它是没有意义的:

package de.richtercloud.type.operator.nonsense;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class A implements Serializable {
    private static final long serialVersionUID = 1L;
    private String b;
    @Id
    private Long id;

    public A() {
    }

    public A(Long id, String b) {
        this.id = id;
        this.b = b;
    }

    public void setB(String b) {
        this.b = b;
    }

    public String getB() {
        return b;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
}

完整的示例可以在中找到。

类型只能用于继承映射

A是继承映射中的A类,A是带有@heritation的路由类,还是扩展了声明了@heritation的类

例如

@Inheritance
@Entity
public class Project

@Entity
public class DesignProject extends Project

@Entity
public class QualityProject extends Project

@Entity
public class SoftwareProject extends Project
现在您可以使用类型

SELECT p
FROM Project p
WHERE TYPE(p) = DesignProject OR TYPE(p) = QualityProject

这种行为是由于休眠错误引起的。上面的例子在OpenJPA中运行良好。

我刚刚研究了这个问题,发现很少有人愿意与您分享。您是否可以尝试使用.class而不是Type从a WHERE a.class=a中选择a,或者为实体类a创建一个存储库,并使用实际的Type查询进行访问-从a WHERE a WHERE TYPEa=a中选择a从a WHERE a.class=a失败,并出现完全相同的错误,这表明这可能是hibernate bug或无意义的反馈。你说的repository是什么意思?一个说jar依赖关系的maven术语?如果是的话,为什么会有什么不同呢?我指的是JPA repsitory和hibernate的.class符号。当我在GitHub上查看您的示例时,请参考该链接,该链接可能对您很有用,@heritation不应该在一个目录上吗?因为B没有子类,因此注释没有意义。看看下面我的项目示例。你能添加一个参考或详细说明吗。为什么这份报告没有提到这一点?你是指根类,对吗?我在没有实体继承的情况下遇到了这个问题,有关详细信息,请参阅更新的问题。我可以通过将继承层次结构中最顶层的类设置为MappedSuperclass来触发这个问题。我不明白你所说的@Inheritation是什么意思,因为有一个默认值InheritanceType.SINGLE_TABLE,也就是说,只有当你引用一个具体的策略并解释它会导致哪些麻烦时,你的语句才有意义。我用这三种策略验证了这个问题。我的意思是你必须用继承树中的实体@在这种情况下,MappedSupperclass不是继承。在示例中,从a中选择a,其中TYPEa=a没有意义,因为a没有继承。所以A永远是我下面的答案。
SELECT p
FROM Project p
WHERE TYPE(p) = DesignProject OR TYPE(p) = QualityProject