将 List<String> 作为参数传递给 postgres 的函数
Pass List<String> into postgres' function as parameter
我有这样的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 子句中,因为我在 DB 函数中有更多的逻辑、变量等等......它必须是 DB 函数。
恐怕我不知道如何使用 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 驱动程序需要一个数组,而不是列表。
我在类似情况下使用了以下解决方法:
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);
不确定这是否增加了很多价值,我只是希望它有所帮助。
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 类型中获取此格式。 Thihs 已经被另一个问题回答了。这个答案只是为了说明这一切的目的。
我有这样的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 子句中,因为我在 DB 函数中有更多的逻辑、变量等等......它必须是 DB 函数。
恐怕我不知道如何使用 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 驱动程序需要一个数组,而不是列表。
我在类似情况下使用了以下解决方法:
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);
不确定这是否增加了很多价值,我只是希望它有所帮助。
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 类型中获取此格式。 Thihs 已经被另一个问题回答了。这个答案只是为了说明这一切的目的。