javapostgresqlref-cursor

How to access the procedure that return setof refcursor from PostgreSQL in Java?


Need to access a procedure that return setof refcursor from PostgreSQL.

I am able to access the first object but not rest of object not rest of objects.

    con.setAutoCommit(false);
    try (CallableStatement proc = 
             con.prepareCall("{ ? = call usp_sel_article_initialdata_new1() }")) {
        proc.registerOutParameter(1, Types.OTHER);
        proc.execute();
        ResultSet results = (ResultSet) proc.getObject(1); 
        while (results.next()) {
            System.out.println("Result Id" + results.getString(1));
            System.out.println("Results Name" + results.getString(2));
    }

This give me the first refcursor values but when i try to use second refcursor it give me error I use this line:

proc.registerOutParameter(2, Types.OTHER);

It is giving errors . Also tried:

proc.registerOutParameter(1, Types.REF);

This also not work. Procedure Example is:

    CREATE OR REPLACE FUNCTION usp_sel_article_initialdata_new1()
    RETURNS SETOF refcursor AS
    $BODY$
    Declare swv_refcur refcursor;
    swv_refcur2 refcursor;
    DECLARE r record;
    BEGIN

    open SWV_RefCur for Select OM.opID as ID,OM.OperatorName as Name from operator
    AS OM (OPid bigint,OperatorName character varying(100),status boolean)
    where OM.status = true 
    order By OperatorName;
    return next SWV_RefCur;

    open SWV_RefCur2 for Select CC.cirid as ID,CC.cirnm as Name from  circle 
    AS CC (cirid bigint,cirnm character varying(100),status boolean)
    where Status = true and cirid not in(28,31) 
    order by cirnm;
    return next SWV_RefCur2;

Please help me how to access second object.


Solution

  • returns setof refcursor means you get a regular ResultSet where each "row" contains another ResultSet when calling getObject():

    The following works for me:

    ResultSet rs = stmt.executeQuery("select * from usp_sel_article_initialdata_new1()");
    if (rs.next())
    {
      // first result set returned
      Object o = rs.getObject(1);
      if (o instanceof ResultSet)
      {
        ResultSet rs1 = (ResultSet)o;
        while (rs1.next())
        {
           int id = rs1.getInt(1);
           String name = rs1.getString(2);
           .... retrieve the other columns using the approriate getXXX() calls
        }
      }
    }
    
    if (rs.next()) 
    {
      // process second ResultSet 
      Object o = rs.getObject(1);
      if (o instanceof ResultSet)
      {
        ResultSet rs2 = (ResultSet)o;
        while (rs2.next())
        {
           ......
        }
      }
    }
    

    From within psql you can also use select * from usp_sel_article_initialdata_new1() you just need to use FETCH ALL afterwards. See the manual for an example: http://www.postgresql.org/docs/current/static/plpgsql-cursors.html#AEN59018

    postgres=> select * from usp_sel_article_initialdata_new1();
     usp_sel_article_initialdata_new1
    ----------------------------------
     <unnamed portal 1>
     <unnamed portal 2>
    (2 rows)
    
    postgres=> fetch all from "<unnamed portal 1>";
     ?column?
    ----------
            1
    (1 row)
    
    postgres=> fetch all from "<unnamed portal 2>";
     ?column?
    ----------
            2
    (1 row)
    
    postgres=>
    

    (I created a dummy function for the above example that only returns a single row with the value 1 for the first cursor and 2 for the second cursor)

    Edit:

    In order for this to work, this needs to be run inside a transaction. Therefor autocommit must be turned off:

    connection.setAutoCommit(false);