如何使用 JPA Criteria 基于 EmbeddedId 的字段进行查询?
How do I query based on fields of EmbeddedId using JPA Criteria?
我花了最后几个小时试图解决这个问题,主要是通过搜索,因为我认为 有人 已经完成了,但我没有找到答案对我有用。
这是我的代码的即时翻译,我可以将其放入 public。
@Entity @Table(name="result")
public class Result implements Serializable {
@Embeddable
public static class ResultPK implements Serializable {
@Column(name="result_date", nullable=false)
@Type(type="com.example.HibernateUTC$LocalDateType") // <- UserType
public LocalDate resultDate;
@Column(name="name", nullable=false)
public String name;
@Column(name="category", nullable=false)
public String category;
public ResultPK() {}
public ResultPK(Date resultDate, String name, String category) {
this.resultDate = resultDate;
this.name = name;
this.category = category;
}
// ...more code for hashCode/equals, no setters or getters...
}
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name="resultDate", column=@Column(name="result_date", nullable = false)),
@AttributeOverride(name="name", column=@Column(name="name", nullable=false)),
@AttributeOverride(name="category", column=@Column(name="category", nullable = false)),
})
private ResultPK resultId;
@Column(name="r_square")
private Double rSq;
@Column(name="p_value")
private pValue;
// ... more code for other fields, setters, getters, but nothing else; vanilla pojo...
}
我有一个隐藏查询的 DAO;我调用的方法是这个
@Repository("resultDAO")
public class ResultDAOImpl extends AbstractBaseDAO<Result> implements ResultDAO {
// boilerplate for intializing base class and other queries
@Override
public List<Result> findDateRange(String category, String name, LocalDate begDate, LocalDate endDate) {
EntityManager em = entityManagerFactory.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Result> q = cb.createQuery(Result.class);
Root<Result> root = q.from(Result.class);
Predicate catMatch = cb.equal(root.get("resultId.category"), category);
Predicate nameMatch = cb.equal(root.get("resultId.name"), name);
Predicate dateRange = cb.between(root.get("resultId.resultDate"), begDate, endDate);
q.select(root).where(cb.and(catMatch, nameMatch, dateRange));
return em.createQuery(q).getResultList();
}
}
当我尝试 运行 执行该查询的代码时,我以错误告终
Exception in thread "main" java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [resultId.category] on this ManagedType [com.example.Result]
我发现的一些类似问题使我看起来需要在查询中使用 resultPK
或 ResultPK
。我已经尝试过那些,没有快乐。我不知道如何指定查询键中的字段,或者我是否需要与此完全不同的东西。我真的需要一个线索...
我正在使用 Spring 4.3.8.RELEASE 和 Hibernate 4.3.11.Final, Java 8(因此使用 UserType 来处理 LocalDate)。
编辑以更正我对实际代码的转录中的一些不一致之处。
您应该这样修改谓词:
Predicate catMatch = cb.equal(root.get("resultId").get("category"), category);
Predicate nameMatch = cb.equal(root.get("resultId").get("name"), name);
Predicate dateRange = cb.between(root.get("resultId").get("resultDate"), begDate, endDate);
顺便说一下,不需要在 where
语句中使用 cb.and
。您可以使用
使代码更短一些
q.select(root).where(catMatch, nameMatch, dateRange);
我花了最后几个小时试图解决这个问题,主要是通过搜索,因为我认为 有人 已经完成了,但我没有找到答案对我有用。
这是我的代码的即时翻译,我可以将其放入 public。
@Entity @Table(name="result")
public class Result implements Serializable {
@Embeddable
public static class ResultPK implements Serializable {
@Column(name="result_date", nullable=false)
@Type(type="com.example.HibernateUTC$LocalDateType") // <- UserType
public LocalDate resultDate;
@Column(name="name", nullable=false)
public String name;
@Column(name="category", nullable=false)
public String category;
public ResultPK() {}
public ResultPK(Date resultDate, String name, String category) {
this.resultDate = resultDate;
this.name = name;
this.category = category;
}
// ...more code for hashCode/equals, no setters or getters...
}
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name="resultDate", column=@Column(name="result_date", nullable = false)),
@AttributeOverride(name="name", column=@Column(name="name", nullable=false)),
@AttributeOverride(name="category", column=@Column(name="category", nullable = false)),
})
private ResultPK resultId;
@Column(name="r_square")
private Double rSq;
@Column(name="p_value")
private pValue;
// ... more code for other fields, setters, getters, but nothing else; vanilla pojo...
}
我有一个隐藏查询的 DAO;我调用的方法是这个
@Repository("resultDAO")
public class ResultDAOImpl extends AbstractBaseDAO<Result> implements ResultDAO {
// boilerplate for intializing base class and other queries
@Override
public List<Result> findDateRange(String category, String name, LocalDate begDate, LocalDate endDate) {
EntityManager em = entityManagerFactory.createEntityManager();
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Result> q = cb.createQuery(Result.class);
Root<Result> root = q.from(Result.class);
Predicate catMatch = cb.equal(root.get("resultId.category"), category);
Predicate nameMatch = cb.equal(root.get("resultId.name"), name);
Predicate dateRange = cb.between(root.get("resultId.resultDate"), begDate, endDate);
q.select(root).where(cb.and(catMatch, nameMatch, dateRange));
return em.createQuery(q).getResultList();
}
}
当我尝试 运行 执行该查询的代码时,我以错误告终
Exception in thread "main" java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [resultId.category] on this ManagedType [com.example.Result]
我发现的一些类似问题使我看起来需要在查询中使用 resultPK
或 ResultPK
。我已经尝试过那些,没有快乐。我不知道如何指定查询键中的字段,或者我是否需要与此完全不同的东西。我真的需要一个线索...
我正在使用 Spring 4.3.8.RELEASE 和 Hibernate 4.3.11.Final, Java 8(因此使用 UserType 来处理 LocalDate)。
编辑以更正我对实际代码的转录中的一些不一致之处。
您应该这样修改谓词:
Predicate catMatch = cb.equal(root.get("resultId").get("category"), category);
Predicate nameMatch = cb.equal(root.get("resultId").get("name"), name);
Predicate dateRange = cb.between(root.get("resultId").get("resultDate"), begDate, endDate);
顺便说一下,不需要在 where
语句中使用 cb.and
。您可以使用
q.select(root).where(catMatch, nameMatch, dateRange);