postgresql 将List< String>作为参数传入postgres的函数

kgqe7b3p  于 2023-03-01  发布在  PostgreSQL
关注(0)|答案(4)|浏览(491)

我有这样的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子句,因为我在数据库函数更多的逻辑,变量等...它必须是数据库函数。

70gysomp

70gysomp1#

在类似的情况下,我使用了以下变通解决方案:
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)在main函数中使用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);
bzzcjhmw

bzzcjhmw2#

恐怕我不知道如何在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驱动程序将期望一个数组,而不是一个列表。

epggiuax

epggiuax3#

不确定这是否增加了很多价值,我只希望它能有所帮助。
PostgreSQL函数期望列表作为输入的最终格式为以下模式,使用数组:

select my_func(array['item1','item2']::my_type[]);

参见完整的on Database Administrators.SE示例。
在您的情况下:

select my_func(array['item1','item2']::text[]);

我在自己的测试中发现

select my_func(array['item1','item2']);

应该够了。
然后,唯一的目标是从你原来的java类型中得到这个格式。这个问题已经被另一个问题回答了。这个答案只是展示了这一切的目的。

gv8xihay

gv8xihay4#

我在使用一个Set<String>时遇到了类似的问题,我想把它作为TEXT[]传递到我的过程中。PostgreSQL认为我的Set<String>是一个varying character。所以我把它转换成一个数组(使用string_to_array()函数),然后再把它转换成一个TEXT[]

@Modifying
@Query(value = "CALL my_procedure(CAST(string_to_array(:mySet, ',') AS TEXT[]))", nativeQuery = true)
void methodName(@Param("mySet") Set<String> mySet);
create procedure my_procedure(list_of_element text[])
    language plpgsql
as
$$
DECLARE
    ...
BEGIN
    ...
END
$$;

相关问题