我正在努力使用Criteria API创建查询。以下SQL查询返回我需要的结果:
SELECT * FROM MODEL WHERE MANUFACTURER_ID = 1 AND SHORTNAME LIKE '%SF%' OR LONGNAME LIKE '%SF%';
我使用条件API编写了以下代码:
public List<Model> findAllByManufacturer(Manufacturer manufacturer,
String pattern) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Model> cq = cb.createQuery(Model.class);
Root<Model> m = cq.from(Model.class);
cq.select(m);
Join<Model, Manufacturer> mf = m.join("manufacturer");
Predicate p = cb.equal(mf.get("id"), manufacturer.getId());
p = cb.and(cb.like(cb.upper(m.<String>get("shortName")),
pattern.toUpperCase()));
p = cb.or(cb.equal(cb.upper(m.<String>get("longName")),
pattern.toUpperCase()));
cq.where(p);
return em.createQuery(cq).getResultList();
}
当我从逻辑上思考它时,它应该起作用:
Predicate p = cb.equal(mf.get("id"), manufacturer.getId());
WHERE MANUFACTURER_ID = 1
p = cb.and(cb.like(cb.upper(m.<String>get("shortName")),
pattern.toUpperCase()));
AND SHORTNAME喜欢'%SF%'
p = cb.or(cb.equal(cb.upper(m.<String>get("longName")),
pattern.toUpperCase()));
或LONGNAME喜欢'%SF%'
查询运行正常,我没有收到任何错误,它只是没有返回任何结果。关于我出错的任何线索都非常感谢!
答案 0 :(得分:6)
您检查过生成的SQL吗?
您正在构建谓词并将其分配给p
,但之后您将创建另一个谓词并将其分配给相同的p
变量。
我认为应该是:
Predicate predicateOnManufacturerId = cb.equal(mf.get("id"),
manufacturer.getId());
Predicate predicateOnShortName = cb.like(cb.upper(m.<String>get("shortName")),
pattern.toUpperCase()));
Predicate predicateOnLongName = cb.equal(cb.upper(m.<String>get("longName")),
pattern.toUpperCase()));
Predicate p = cb.or(cb.and(predicateOnManufacturerId,
predicateOnShortName),
predicateOnLongName);
cq.where(p);
另外,为什么不使用实体的元模型:
Join<Model, Manufacturer> mf = m.join(Model_.manufacturer);
... cb.equal(mf.get(Manufacturer_.id);
...
它更加类型安全,您可以在编译时检测不正确的查询,而不是运行时。