我想使用criteriaUpdate来创建这样的更新查询:
UPDATE <SOME TABLE>
SET SELECTED = !SELECTED
WHERE
[DYNAMIC QUERY HERE]
我能找到的最接近的是代码:
public <T> Query createRevertSelectionQuery(Class<T> clazz, EntityManager em, Specification<T> s) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaUpdate<T> criteriaUpdate = cb.createCriteriaUpdate(clazz);
Root<T> root = criteriaUpdate.from(clazz);
Predicate p = cb.and(new Predicate[] {s.toPredicate(root, null, cb)});
Expression<Boolean> e =cb.not((root.get("selected").as(Boolean.class)));
Path<Boolean> selected = root.get("selected");
criteriaUpdate.set(selected, e);
criteriaUpdate.where(p);
Query q = em.createQuery(criteriaUpdate);
return q;
}
但是失败,因为我得到以下查询:
update com.redknee.suspense.mgt.model.Moc as generatedAlias0
set generatedAlias0.selected = generatedAlias0.selected <> true
where
[dynamic query]
给我错误
org.hibernate.hql.internal.ast.QuerySyntaxException:意外令牌:<>在第1行第118列附近
有人可以帮忙吗?
答案 0 :(得分:0)
我不确定这是一个错误还是只是不打算以这种方式使用。
在子句中,NOT和任何其他操作数都像一个超级字符一样工作。但是,无论您尝试什么,Hibernate查询构建器似乎总是可以优化括号(在我看来,始终使用括号但仅是一种观点可能仍然是一个好习惯)。
强制括号的一种方法是使用JPA Subquery
。请参见以下示例。请注意,我根据自己的喜好稍微更改了JPA对象名称,并且不包括Specification
,因为它与该解决方案无关:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaUpdate<T> update = cb.createCriteriaUpdate(clazz);
Root<T> from = update.from(clazz);
Path<Boolean> selected = from.get("selected");
// Subquery just "joins back" to the same row and
// returns a negated boolean value of "selected" from the original row
Subquery<Boolean> subSelect = update.subquery(Boolean.class);
Root<T> subFrom = subSelect.from(clazz);
subSelect.select(cb.not(selected));
subSelect.where(cb.equal(from.get("id"), subFrom.get("id")));
update.set(selected, subSelect);