Общие критерииUpdate set boolean =! Boolean - PullRequest
0 голосов
/ 10 ноября 2018

Я хочу использовать критерий обновления для создания запроса на обновление, подобного следующему:

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

Кто-нибудь может помочь, пожалуйста?

1 Ответ

0 голосов
/ 11 ноября 2018

Я не уверен, является ли это ошибкой или она просто не предназначена для использования таким образом.

В операторе where-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);
...