Reputation: 300
I made a Postgres stored procedure:
CREATE OR REPLACE FUNCTION GetUser(ipUserId integer)
RETURNS setof users AS $$
BEGIN
IF ipUserId is null THEN
return query select * from users A order by modifieddate desc;
END IF;
return query select * from users where iduser = ipUserId;
END;
$$ LANGUAGE plpgsql;
I tried to use it in java like this:
StoredProcedureQuery query = entityManager.createStoredProcedureQuery("GetUser").
registerStoredProcedureParameter("ipUserId",
Integer.class, ParameterMode.IN)
.registerStoredProcedureParameter("users",
List.class, ParameterMode.OUT)
.setParameter("postId", 1);
or
StoredProcedureQuery query = entityManager.createStoredProcedureQuery("GetUser")
.registerStoredProcedureParameter(1,void.class, ParameterMode.REF_CURSOR)
.registerStoredProcedureParameter(2,Integer.class, ParameterMode.IN)
.setParameter(2, ipIdUser);
I want to store the result in a List.
What and how should i do, because i'm getting all kind of errors?
Update :
Those are the errors :
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: Error calling CallableStatement.getMoreResults
Caused by: org.hibernate.exception.SQLGrammarException: Error calling CallableStatement.getMoreResults
at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
at org.hibernate.result.internal.OutputsImpl.convert(OutputsImpl.java:79)
at org.hibernate.result.internal.OutputsImpl.<init>(OutputsImpl.java:56)
at org.hibernate.procedure.internal.ProcedureOutputsImpl.<init>(ProcedureOutputsImpl.java:34)
at org.hibernate.procedure.internal.ProcedureCallImpl.buildOutputs(ProcedureCallImpl.java:453)
at org.hibernate.procedure.internal.ProcedureCallImpl.getOutputs(ProcedureCallImpl.java:404)
at org.hibernate.procedure.internal.ProcedureCallImpl.outputs(ProcedureCallImpl.java:663)
at org.hibernate.procedure.internal.ProcedureCallImpl.getResultList(ProcedureCallImpl.java:751)
... 21 more
Caused by: org.postgresql.util.PSQLException: A CallableStatement was executed with an invalid number of parameters
Upvotes: 2
Views: 3914
Reputation: 221265
In your case, you have a table valued function that happens to map to an actual table, so the approach using the JPA native query is elegant too, but perhaps your projection is something different, or you return multiple nested data structures, arrays, etc, where working with JPA might be tricky.
jOOQ generates code for all of your procedures, including table valued functions. For example, you'll have a Routines
class containing a getUser
method, which you can query like this:
Result<GetUser> result = Routines.getUser(configuration, 1);
You can also use the table valued function as an actual table in the query, like this:
Result<GetUser> result = ctx.selectFrom(GETUSER(1)).fetch();
Disclaimer: I work for the company behind jOOQ.
Upvotes: 0
Reputation: 745
Why not use getResultList
on StoredProcedureQuery
? This avoids having to do the string manipulation.
List<User> users = entityManager.createStoredProcedureQuery("GetUser")
.registerStoredProcedureParameter("ipUserId", Integer.class, ParameterMode.IN)
.setParameter("ipUserId", ipIdUser)
.getResultList();
Upvotes: 0
Reputation: 300
I found a much simple solution, just make a SQL Query to call the procedure with hibernate.
String SqlString = "select * from GetUser({0})";
if (ipIdUser == null )
SqlString = MessageFormat.format(SqlString, "NULL");
else
SqlString = MessageFormat.format(SqlString, ipIdUser);
LOGGER.info("SqlSting =" + SqlString);
return entityManager.createNativeQuery(SqlString, User.class)
.getResultList();
Upvotes: 1
Reputation: 127
You can try using CallableStatement. Assuming that your Connection var is OK:
CallableStatement stmt = con.prepareCall("{call SCHEMA.PROCEDURE_NAME (?, ?)}");
stmt.setInt(1, custom_var);
stmt.registerOutParameter(2, OracleTypes.INTEGER);
stmt.execute();
To get result: stmt.getInt(3); stmt.getString(4)
If you can't succeed try using JdbcTemplate:
SimpleJdbcCall call = new SimpleJdbcCall(this.jdbcTemplate).withSchemaName(SCHEMA).withProcedureName(PROC);
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("ipUserId", custom_var);
Map out = call.execute(params);
To get single result: Integer.parseInt("" + out.get("OUT_PARAM_NAME")); (String) out.get("OUT_PARAM_NAME2"));
Or you can save all the result in a list to work on it later:
SimpleJdbcCall call = new SimpleJdbcCall(this.jdbcTemplate);
List<Map<String, Object>> rows = call.getJdbcTemplate().queryForList(PROC_STRING, new Object[] { param1, param2 });
Upvotes: 1