Postgres:将自定义类型从Java传递到Postgres函数

Postgres:将自定义类型从Java传递到Postgres函数,java,postgresql,plpgsql,Java,Postgresql,Plpgsql,我有一个postgres函数,它接受一个复杂的用户定义类型作为输入 CREATE OR REPLACE FUNCTION addUser(user IN O_USER) RETURNS VOID AS $$ BEGIN end; $$ language plpgsql; CREATE TYPE O_USER AS ( id NUMERIC, name VARCHAR(50), addresses O_ADDRESS[] ); CREATE TYPE O_ADDRESS AS

我有一个postgres函数,它接受一个复杂的用户定义类型作为输入

CREATE OR REPLACE FUNCTION addUser(user IN O_USER) RETURNS VOID
AS
$$
BEGIN

end;
$$ language plpgsql;

CREATE TYPE O_USER AS (
  id NUMERIC,
  name VARCHAR(50),
  addresses O_ADDRESS[]
);


CREATE TYPE O_ADDRESS AS (
  id NUMERIC,
  city VARCHAR(50)
);
现在我需要从Java调用这个函数。 我的理解是,我需要传递一个字符串,该字符串将由db类型转换到UDT

当我传递没有地址的用户时,它工作正常。但是如果我也传递了地址数组,那么它就给出了错误

ERROR:  malformed array literal: "{(1"
DETAIL:  Unexpected end of input.
SQL state: 22P02
Character: 23
我也可以用postgres select语句重现这个问题。例如,下面的工作很好

Select * from addUser('(1, "Vishal", {})');
但是当我传递地址时,那就是个问题

Select * from addUser('(1, "Vishal", {(1,"tet")})');
Select * from addUser('(1, "Vishal", {"(1,)"})');
Select * from addUser('(1, "Vishal", {"(1,null)"})')
我相信我不能正确地构造字符串。你知道这里怎么了吗

更新

调用函数的Java代码

import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.StoredProcedure;

import javax.sql.DataSource;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;

public class AddUserProcedurePostgres extends StoredProcedure {

    public AddUserProcedurePostgres(DataSource dataSource) {
        super(dataSource, "addUser");
        setFunction(true);

        declareParameter(new SqlParameter("i_User", Types.OTHER, "O_USER"));

        compile();
    }

    public void execute() {

        Map<String, Object> input = new HashMap<>();
        input.put("i_User", "(1, Vishal, array[(1,tet)]::O_ADDRESS[])");

        execute(input);
    }

}

您需要使用
array
literal传递
O\u地址
数组,并将数组键入
O\u地址[]
。以下
select
语句有效

select * from addUser(cast(row(1, 'Vishal', array[cast(row(1,'tet') as O_ADDRESS)]) as O_USER));

select * from addUser((1, 'Vishal', array[]::O_ADDRESS[])::O_USER);

select * from addUser((1, 'Vishal', array[]::O_ADDRESS[]));

select * from addUser((1, 'Vishal', array[(1,'tet')]::O_ADDRESS[]));

我找到了两种将所需值传递给函数的方法:

  • 如果UDT的字符串很复杂,则很难创建该字符串。最简单的方法是进行逆向工程。在plpgsql中创建UDT并打印它。这样,您将获得需要从Java传递的字符串。现在在Java代码中编写一个逻辑来创建这样的字符串
  • 另一种方法是以json格式传递值,然后在函数中解析json并自己构造UDT

  • 我选择第二种方法,因为它易于维护。

    感谢@Rahul Sharma的回复。正如我所说,我需要从Java调用函数。不确定如何从Java代码中传递数组文本。您只需要从代码中构建字符串。不知道问题在哪里。可能,您可以显示一些代码,其中您正在生成查询并且在构建字符串时遇到困难。我已在问题中添加了Java代码,用于调用函数。首先修改此字符串
    “(1,Vishal,array[(1,tet)]::O_ADDRESS[])”
    “(1,'Vishal',array[(1,'tet')::O_ADDRESS[])”
    。在代码将查询转换为字符串之前,尝试添加日志,并查看生成的字符串是什么。我按照建议更改了参数,但出现了相同的错误。参数是
    (1,'Vishal',array[(1,'tet')]::O_ADDRESS[])
    ,查询结果是
    select*from addUser(?)
    
    select * from addUser(cast(row(1, 'Vishal', array[cast(row(1,'tet') as O_ADDRESS)]) as O_USER));
    
    select * from addUser((1, 'Vishal', array[]::O_ADDRESS[])::O_USER);
    
    select * from addUser((1, 'Vishal', array[]::O_ADDRESS[]));
    
    select * from addUser((1, 'Vishal', array[(1,'tet')]::O_ADDRESS[]));