我有3个问题的表:PrblFldr - > PrblFldrAtrbtVal - > PrblTmpltAtrbt。这些关系分别是“一对多”和“多对一”。具有一对多和多对一关系的CriteriaQuery
我使用CriteriaBuilder
在PrblFldr
对象上执行搜索。我需要搜索与PrblFldr
相关的每个PrblFldrAtrbtVal
的值。查询参数的键是将每个PrblFldrAtrbtVal
与PrblTmpltAtrbt
相关联的唯一PK;该参数的值是在PrblFldrAtrbtVal
的值中搜索的值。
这里是我到目前为止的代码(编辑):
@GET
@Path("/folders/search")
public Response searchFolders(@Context UriInfo uriInfo) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<PrblFldr> cq = cb.createQuery(PrblFldr.class);
Root<PrblFldr> folder = cq.from(PrblFldr.class);
Join<PrblFldr, PrblFldrAtrbtVal> attributes = folder.join("prblFldrAtrbtVals");
Join<PrblFldrAtrbtVal, PrblTmpltAtrbt> attributeTemplates = attributes.join("prblTmpltAtrbt");
List<Predicate> predicates = new ArrayList<Predicate>();
MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
for (String key: queryParams.keySet()) {
String value = queryParams.getFirst(key).replaceAll("_", "\\\\_");
predicates.add(cb.and(cb.equal(attributeTemplates.<String>get("tmpltAtrbtSeqId"), key),
cb.like(attributes.<String>get("fldrAtrbtVal"), "%" + value + "%", '\\')));
}
cq.distinct(true).select(folder).where(cb.and(predicates.toArray(new Predicate[]{})));
List<PrblFldr> results = em.createQuery(cq).getResultList();
return Response.ok(gson.toJson(results), MediaType.APPLICATION_JSON).build();
}
编辑:这是目前工作,如果我只在一个键/值对搜索通过。如果我传入多个PrblFldrAtrbtVal
进行搜索,则会返回空白结果集,尽管一个或多个PrblFldr
对象应该与指定的PrblFldrAtrbtVal
对象相匹配。
我认为这与cq.where()
条款中的cb.and()
声明有关。我确实需要一个'AND',但为什么没有返回结果?
哦,我明白了,但是我不希望'OR'子句是在它们被转换为数组时的谓词上吗?我确实希望for循环中的两个语句是AND'ed,因为它们确保值和'tmpltAtrbtSeqId'匹配正确的'PrblFldrAtrbtVal'。 –
我在尝试您的建议后编辑了我的原始帖子。请参阅新的问题。 –
我认为你需要在查询中添加一个'DISTINCT'。请检查http://stackoverflow.com/questions/10731723/how-to-add-distinct-in-hibernate-criteria – Priyesh