Как конвертировать SQL Query с помощью CriteriaQuery - PullRequest
0 голосов
/ 21 мая 2019

Я хочу преобразовать свой SQL-запрос из SQL в CriteriaQuery, у меня есть этот SQL-запрос:

1)

SELECT * FROM table AS t WHERE id = (SELECT MAX(id) FROM table AS t WHERE t.element_id = 354 AND (name <> 'foo' OR (name = 'bar' AND event = 'foo')));

2)

SELECT tr1.*
FROM table AS tr1
INNER JOIN (SELECT MAX(id) AS id FROM table AS tr WHERE tr.element_id = 354 AND (name <> 'foo' OR (name = 'bar' AND event = 'foo'))) AS tr2
ON tr1.id = tr2.id;

Каклучший способ сделать это?

public Predicate createsubqueryDateGreaterThanTest(CriteriaBuilder cb, Root<? extends Entity> root, Date inputDate){         
        // create the outer query
        CriteriaQuery<Date> cq = cb.createQuery(Date.class);

        Root<Table> rootQuery = cq.from(Table.class);
        Subquery<Table> sub = cq.subquery(Table.class);
        Root<Table> subRoot = sub.from(Table.class);
        //sub.select(subRoot);
        cq.multiselect(rootQuery);
        sub.select(subRoot)
        //cq.multiselect(rootQuery.select(cb.max(Table_.elementId)));
        //sub.select(cb.greatest(cb.get(Entity_.element).get("id")));
        //cq.multiselect(subRoot.select(cb.greatest(Table_.elementId)))
            .where(
                    cb.greaterThanOrEqualTo(subRoot.get(Table_.date), inputDate),
                    cb.equal(root.get(Entity_.element).get("id"), subRoot.get(Table_.elementId)),
                    cb.notEqual(subRoot.get(Table_.name), "foo"),
                    cb.or(
                         cb.equal(subRoot.get(Table_.name), "bar"),
                         cb.and(cb.equal(subRoot.get(Table_.event), 'foo'))
                        )
                );

        return cb.exists(sub);
    }

Запрос выполняется, но результат неверен.

1 Ответ

0 голосов
/ 21 мая 2019

Из того, что я помню, это должно быть представление вашего первого запроса.

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

Используйте ParameterExpression для непостоянных параметров, чтобы убедиться, что сервер может повторно использовать запрос. В противном случае необходимо проанализировать и перепланировать каждый новый запрос.

Но в этом случае выражения ParamterExpression, похоже, не работают правильно, возможно, это проблема Hibernate (для проверки я использовал 5.4.2.Final).

Ps .: Вам следует избегать использования ключевых слов «sql» для идентификаторов таблиц, поэтому вместо именования таблицы «table» используйте что-то еще.

SELECT * FROM table AS t WHERE id = (SELECT MAX(id) FROM table AS t WHERE t.element_id = 354 AND (name <> 'foo' OR (name = 'bar' AND event = 'foo')));
        CriteriaQuery<Table> criteriaQuery = cb.createQuery(Table.class);
        Root<Table> root = criteriaQuery.from(Table.class);

        Subquery<Integer> sub = criteriaQuery.subquery(Integer.class);
        Root<Table> subRoot = sub.from(Table.class);

        criteriaQuery.where(
                cb.equal(subRoot.get(Table_.element_id), 354),
                cb.or(cb.notEqual(subRoot.get(Table_.name), "foo"),
                      cb.and(cb.equal(subRoot.get(Table_.name), "bar"), 
                             cb.equal(subRoot.get(Table_.event), "foo"))));

        sub.select(cb.max(subRoot.get(Table_.id)));

        criteriaQuery.where(cb.equal(root.get(Table_.id), sub));
        criteriaQuery.select(root);

        List<Table> result =
        entityManager.createQuery(criteriaQuery)
        .getResultList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...