Функции, возвращающие набор PostgreSQL, не разрешены при использовании JPA

#sql #postgresql #jpa #sql-function

#sql #postgresql #jpa #sql-функция

Вопрос:

У меня есть функция sql, которая выглядит как:

 CREATE OR  replace FUNCTION search(IN word character VARYING) 
returns setof certificates AS $$SELECT c 
FROM   certificates c 
WHERE  Upper(description) LIKE Upper('%'||word||'%') 
OR Upper(NAME) LIKE Upper('%' 
              ||word 
              ||'%') $$ language sql;
  

И я пытаюсь вызвать это с помощью JPA, например:

 SELECT c FROM Certificates c WHERE c in (function('search',:findPhrase ))
  

И я получаю set-returning functions are not allowed in WHERE
Но если я изменю возвращаемый тип моей функции sql на просто сертификаты вместо набора сертификатов, это сработает. Но он находит только 1 запись.
Я пробовал разные вещи, включая преобразование результата в массив и использование идентификаторов вместо целых объектов. На самом деле ничего не помогает.
Итак, вопрос в том, как заставить мой код работать по желанию?

Я упростил свой реальный случай, чтобы просто показать проблемную часть. Весь SQL больше похож:

 SELECT c FROM Certificates 
JOIN c.tags t WHERE t.name IN :names "
"GROUP BY (c.id) "
"HAVING COUNT(c.id) >= :size
  AND c IN (function('search',:findPhrase )) 
  

В конце я переключил свой TypedQuery на NativeQuery и использовал этот код

 AND c in(select search(:findPhrase))
  

Итак, весь SQL теперь выглядит так

 SELECT * FROM certificates c JOIN certificate_tags ct ON c.id = ct.certificate_id JOIN tags t ON t.id = ct.tag_id WHERE t.name IN (?) GROUP BY (c.id, ct.id, t.id) HAVING COUNT(c.id) >= ? AND c in(select search(?))
  

Ответ №1:

Вам нужно select указать набор, который возвращает функция. Я думаю, вы просто хотите:

 select * from function('search',:findPhrase) c
  

Postgres даже позволяет:

 select function('search',:findPhrase) c
  

Комментарии:

1. Я попытался ВЫБРАТЬ c ИЗ Certificates JOIN c.теги t, ГДЕ t.name В : имена » «ГРУППИРУЮТСЯ ПО (c.id ) » «ИМЕЯ КОЛИЧЕСТВО (c.id ) >= :size И c В ( выберите функцию (‘search’,:findPhrase) ), Но теперь он говорит: Нет типа данных для узла

2. @DenisBahlei: похоже, это другая проблема. Пожалуйста, начните с выполнения этого запроса, как указано, и посмотрите, работает ли он.

3. Итак, я попытался запустить этот SELECT c ИЗ GiftCertificate c, ГДЕ c в (select function (‘search’,:findPhrase)), и у меня нет типа данных для узла: org.hibernate.hql.internal.ast.tree. MethodNode