我有3个表有问题:PrblFldr-> PrblFldrAtrbtVal-> PrblTmpltAtrbt。这些之间的关系分别是“一对多”和“多对一”。

我正在使用CriteriaBuilderPrblFldr对象执行搜索。我需要按与PrblFldrAtrbtVal关联的每个PrblFldr的值进行搜索。查询参数的键是将每个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对象匹配,但仍返回空白结果集。

我认为这与cb.and()子句中的cq.where()语句有关。我确实想要一个“与”,但是为什么不返回任何结果呢?

最佳答案

查询返回一个空列表,因为谓词添加了“ AND”。
即,正在生成的查询类似于

tmpltAtrbtSeqId = '1' AND fldrAtrbtVal like '%a%'
AND tmpltAtrbtSeqId = '2' AND fldrAtrbtVal like '%b%'
AND tmpltAtrbtSeqId = '3' AND fldrAtrbtVal like '%c%'


当您传递多个键/值对时。

您需要在for循环中添加“ OR”子句。

关于java - 具有一对多和多对一关系的CriteriaQuery,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22637643/

10-10 04:36