问题
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.
回答1:
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);
回答2:
When i call stored procedures i use EntityManager. Below I attached simple example:
//StoredProcedureQuery storedProcedure = entityManager.createStoredProcedureQuery("[database_name].[schema_name].[procedure_name]");
StoredProcedureQuery storedProcedure = entityManager.createStoredProcedureQuery("[Mydatabase].[dbo].[process_user]");
//registering INPUT parameters
storedProcedure.registerStoredProcedureParameter("Id",Integer.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("Name",String.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter("UserType",Integer.class, ParameterMode.IN);
//registering OUTPUT parameters
storedProcedure.registerStoredProcedureParameter("ErrorCode",Integer.class, ParameterMode.OUT);
storedProcedure.registerStoredProcedureParameter("ErrorMessage",String.class, ParameterMode.OUT);
//setting INPUT parameters
storedProcedure.setParameter("Id", 12345);
storedProcedure.setParameter("Name", "Mick");
storedProcedure.setParameter("UserType", 1);
//executing procedure
storedProcedure.execute();
//getting results
Integer errorCode = (Integer) storedProcedure.getOutputParameterValue("ErrorCode");
String errorMessage = (String) storedProcedure.getOutputParameterValue("ErrorMessage");
Hope this will help
回答3:
This worked for me in following version
springframework-version :- 4.2.1.RELEASE
hibernate.version:- 5.0.1.Final
postgresql.version :- 9.1-901-1.jdbc4
// Call the stored procedure
ProcedureCall procedureCall = getSession().createStoredProcedureCall("get_all_matching_email_profile");
// Register the output parameter, postgres support ref_cursor as first parameter only, so don't change it
procedureCall.registerParameter(1, void.class, ParameterMode.REF_CURSOR);
// Inpur parameters
procedureCall.registerParameter(2, BigDecimal.class, ParameterMode.IN);
procedureCall.registerParameter(3, String.class, ParameterMode.IN);
procedureCall.getParameterRegistration(2).bindValue(companyId);
procedureCall.getParameterRegistration(3).bindValue(tempArray[i]);
// Execute the procedure and get the result
ProcedureOutputs procedureOutputs = procedureCall.getOutputs();
ResultSetOutput resultSetOutput = (ResultSetOutput)procedureOutputs.getCurrent();
List results = resultSetOutput.getResultList();
log.info("The result is "+results.size());
for(Integer j=0;j<results.size();j++) {
Object[] objects = (Object[]) results.get(j);
log.info("The result is "+objects.length);
}
来源:https://stackoverflow.com/questions/25718791/how-to-access-the-procedure-that-return-setof-refcursor-from-postgresql-in-java