#postgresql #jpa #querydsl
#postgresql #jpa #querydsl
Вопрос:
Я пытаюсь создать запрос, который использует оператор наложения массива postgresql в QueryDSL JPA, используя BooleanBuilder и boolean template, однако я не могу заставить JPA принять мой запрос. В настоящее время я написал его так
public BooleanBuilder addUUIDListIntersectionCondition(BooleanBuilder clause,
CollectionPath<UUID, ComparablePath<UUID>> arg0, List<UUID> arg1) {
clause.and(Expressions.booleanTemplate("{0} amp;amp; ARRAY[{1}::UUID]", arg0,
String.join(",", arg1.stream().map(a -> a.toString()).collect(Collectors.toList()))));
}
но это приводит к следующему исключению:
An exception occurred while creating a query in EntityManager:
Exception Description: Syntax error parsing [select ec
from vw_ec ec
where ec.orgUserIds amp;amp; ARRAY[?1::UUID]].
[76, 193] The expression is not a valid conditional expression.; nested exception is java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager:
Exception Description: Syntax error parsing [select ec
from vw_ec ec
where ec.orgUserIds amp;amp; ARRAY[?1::UUID]].
[76, 193] The expression is not a valid conditional expression.
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:374)
at org.springframework.orm.jpa.DefaultJpaDialect.translateExceptionIfPossible(DefaultJpaDialect.java:128)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
Выполнение аналогичного запроса непосредственно в postgresql работает так, как задумано:
select *
from ec ec
where (ec.orgUserIds amp;amp; array['c61d452e-0361-11eb-8ecd-9e48108033fa', 'c623fc2d-0361-11eb-8ecd-9e48108033fa'::UUID])
Есть идеи о том, где я ошибаюсь?
Комментарии:
1. Я попытался обернуть оверлейный oeprator в функцию базы данных и вызвать ее вместо этого, но теперь я получаю внутреннее исключение: java.lang. ClassCastException: класс org.eclipse.persistence.mappings.structures. Сопоставление массива не может быть приведено к классу org.eclipse.persistence.mappings. Сопоставление коллекций при попытке вызвать эту функцию.
2. Дайте мне знать, если вы уже выяснили, как должна быть составлена рабочая booleanTemplate с точно таким же запросом ec.orgUserIds amp;amp; array[‘c61d452e-0361-11eb-8ecd-9e48108033fa’, ‘c623fc2d-0361-11eb-8ecd-9e48108033fa’]::uuid[]. Я столкнулся с той же проблемой.
3. Мне удалось сделать работоспособным только такой запрос c.orgUserIds amp;amp; array[‘c61d452e-0361-11eb-8ecd-9e48108033fa’]::uuid[], где arg1 имеет только один элемент, использующий booleanTemplate: «Expressions.booleanTemplate(«{0} amp;amp; ARRAY[{1}]::uuid[]», ec.orgUserIds, StringUtils.collectionToDelimitedString(arg1, «,», «‘», «‘»))» Но этот синтаксис не работает для меня, если arg1 содержит более 1 элемента — вызывает исключение PostgresqlBadGrammarException: неправильная длина UUID. Шаблон QueryDSL выглядит так, что интерпретирует весь входной параметр для МАССИВА как строку. Использование string_to_array вместо ARRAY мне тоже не помогает
Ответ №1:
Не думаю, что у меня есть чистое решение, но оно работает для следующего запроса:
select *
from ...
where '{e48f54d5-9845-4987-a53d-e0ecfe3dbb43,e48f54d5-9845-4987-a53d-e0ecfe3dbb45}'::uuid[] amp;amp; '{e48f54d5-9845-4987-a53d-e0ecfe3dbb40,e48f54d5-9845-4987-a53d-e0ecfe3dbb45}'::uuid[];
Я использую следующий синтаксис в booleanTemplate
:
select(...)
.from(...)
.where(new BooleanBuilder().and(Expressions.booleanTemplate("{0} amp;amp; {1}::uuid[]", arg0, String.format("{%s}", arg1.stream().map(UUID::toString).collect(joining(",")))))
Комментарии:
1. О, интересно, так вы смогли заставить его работать, используя booleanTemplate в инструкции select, а не внутри where ? Это лучше, чем невозможность использовать все это, но было бы неплохо иметь возможность фильтровать по функции.
2. Я пробовал ваше предложение, но я всегда получаю ошибку в JPA до фактического выполнения запроса. [1258, 1504] Выражение не является допустимым условным выражением. [1504, 1814] Запрос содержит искаженное окончание.] 2020-10-16 22:09:57.230 DEBUG 10 — [nio-8080-exec-6] o.j.s.OpenEntityManagerInViewInterceptor : закрытие JPA EntityManager в OpenEntityManagerInViewInterceptor
3. Я исправил ответ, чтобы было немного понятно. В предложении where используется BooleanTemplate. Попробуйте этот пример.