Java 为什么我不能用与JPA2.1中的实体类型匹配的TYPE-WHERE子句查询实体?
实体类A形式的查询,形式为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的超类实例以及子类实例 例
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