Как использовать Querydsl для построения сложного предиката, включающего несколько таблиц? - PullRequest
0 голосов
/ 05 августа 2020

Я пытаюсь использовать Querydsl для получения некоторых результатов из таблицы. Пока что это то, что я пробовал -

Предположим, есть 5 сущностей с именами T1..T5. И я пытаюсь выполнить этот запрос SQL в Querydsl -

SELECT T1.*
FROM T1,T2,T3,T4,T5
WHERE T1.A=T2.A
AND T2.B=T5.B
AND T4.C=T2.C
AND T1.B=1234;

Я пробовал следующее, но запрос Hibernate продолжает выполняться и, похоже, не завершается.

booleanBuilder.and(JPAExpressions.select(qT1).from(qT1,qT2,qT3,qT4,qT5)
.where(
    qT1.a.eq(qT2.a)
    .and(qT1.a.eq(qT2.a))
    ... // and so on
    .exists());

Я использую репозиторий, расширяющий QuerydslPredicateExecutor, и findAll для выполнения этого. Проблема в том, что запрос выполняется бесконечно. И меня интересует только первый результат, который может появиться. Итак, где я ошибаюсь, заставляя запрос выполняться вечно?

Изменить: вместо этого я решил использовать JPAQuery. И, конечно же, сгенерированный запрос Hibernate такой же. Вот мой JPAQuery.

JPQLQuery jpqlQuery = new JPAQuery(entityManager);
        jpqlQuery.select(qT1).from(qT1, qT2, qT3, qT4, qT5).where(booleanBuilder);
        return jpqlQuery.fetch();

Как мне включить limit в приведенный выше JPAQuery, чтобы был получен только первый результат?

1 Ответ

1 голос
/ 05 августа 2020

Сложность не в предикате или QueryDSL, а в том, что вы выполняете его в подзапросе, который должен выполняться для каждой строки в результате. В зависимости от общего размера набора результатов, это может стать все труднее вычислить. Однако это одинаково сложно для QueryDSL, Hibernates HQL, JPA JPQL или ваших баз данных SQL. Таким образом, SQL, который вы пытаетесь сгенерировать, будет таким же медленным.

Возможно, вам удастся оптимизировать запрос с помощью предложения limit. Добавление предложения limit в запрос в QueryDSL довольно тривиально: .limit(1). Итак, ваш запрос становится:

JPQLQuery jpqlQuery = new JPAQuery(entityManager);
        jpqlQuery.select(qT1).from(qT1, qT2, qT3, qT4, qT5).where(booleanBuilder);
        jpqlQuery.limit(1);
        return jpqlQuery.fetch();
...