Передать список <String>в функцию postgres в качестве параметра - PullRequest
2 голосов
/ 14 марта 2019

У меня есть интерфейс хранилища данных Spring, подобный этому:

public interface MyEntityRepository extends 
        JpaRepository<MyEntity, Long> {

    @Query(nativeQuery = true, value = "select * from my_func(:myList)")
    Page<MyEntity> findBy(
            @NonNull @Param("myList") List<String> myList,
            @NonNull Pageable pageable);

}

Функция Postgres Я определил вот так (но я могу изменить ее, если я сделал это неправильно):

CREATE OR REPLACE FUNCTION my_func(variadic myList text[])
RETURNS SETOF myEntityTable AS $$
... some logic
select * from myEntityTable t where t.foo in (myList);

Когда я вызываю этот метод репозитория, я получаю эту ошибку:

ERROR: operator does not exist: character varying = text[]
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Where: PL/pgSQL function f_najdi_autorizaciu_na_spracovanie(text[]) line 28 at RETURN QUERY

Можете ли вы сказать мне, какой тип я должен использовать в моей функции postgres?Спасибо за совет.

РЕДАКТИРОВАТЬ: Я не могу использовать собственный запрос выше метода репозитория и передать там список в предложении IN, потому что у меня в функции БД больше логики, переменных и так далее ... это должна быть функция БД.

Ответы [ 2 ]

1 голос
/ 15 марта 2019

В похожей ситуации я использовал следующее решение:

1) Создал две вспомогательные функции:

-- Convert a variable number of text arguments to text array
-- Used to convert Java collection to the text array
--
create or replace function list_to_array(variadic _list text[]) returns text[] language sql as $$
select _list;
$$;
-- Convert the bytea argument to null.
-- Used to convert Java null to PostgreSQL null
--
create or replace function list_to_array(_list bytea) returns text[] language sql as $$
select null::text[];
$$;

2) Использовал any вместо inв основной функции, например:

create or replace function my_func(_params text[]) 
returns table (field1 text, field2 text) 
language sql as 
$$
select
  t.field1 as field1,
  t.field2 as field2,
from
  my_table t
where
  array_length(_params, 1) is null or t.foo = any(_params);
$$;

3) Затем использовать их в методе хранилища, например:

@NonNull
@Query(value = "select ... from my_func(list_to_array(?1))", nativeQuery = true)
List<MyProjection> getFromMyFunc(@Nullable Set<String> params, @NonNull Pageable page);
0 голосов
/ 14 марта 2019

Боюсь, я не знаю, как это сделать с Spring Data JPA, но с простым JDBC вам придется просто привести переменную связывания к text[] и передать тип String[] вместо список. Например:

try (PreparedStatement s = conn.prepareStatement("select * from my_func(?::text[])")) {
    s.setObject(1, myList.toArray(new String[0]));

    try (ResultSet rs = s.executeQuery()) {
        // ...
    }
}

Ключевое сообщение здесь заключается в том, что драйвер JDBC ожидает массив, а не список.

...