I am calling postgreSQL function from Java using SimpleJdbcCall and extracting the output in ResultSet, while the function returns data when run in postgre but in Java it is giving null result.
Here is my postgre function that I am calling:
CREATE OR REPLACE FUNCTION package.getdemojob(create_user_id character varying)
RETURNS TABLE(batch_id bigint, content_id character varying, start_date timestamp without time zone,
end_date timestamp without time zone)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN query
SELECT MY_TABLE.BATCH_ID, MY_TABLE.CONTENT_ID, MY_TABLE.START_DATE, MY_TABLE.END_DATE
FROM MY_TABLE
WHERE MY_TABLE.CREATE_USER = create_user_id
ORDER BY BATCH_ID;
END;
$function$
;
Java code that I am using to call this function is:
this.demoGetJob = new SimpleJdbcCall(jdbcTemplate)
.withCatalogName("package")
.withProcedureName("getdemojob")
.withoutProcedureColumnMetaDataAccess()
.useInParameterNames("create_user_id")
.declareParameters(
new SqlParameter("create_user_id", Types.VARCHAR)
);
SqlParameterSource in = new MapSqlParameterSource().addValue("create_user_id", userId);
ResultSet rs = demoGetJob.executeFunction(ResultSet.class, in);
while(rs.next()){
System.out.println(rs.getInt("batch_id"));
}
On line rs.next() I am getting nullPointerException though there is data present in MY_TABLE with the given create_user_id
What wrong am I doing?
Thanks in advance.
Related
I have my Oracle DB Stored Function as below:
CREATE OR REPLACE FUNCTION FN_EMP_CNT (EMP_ID NUMBER) RETURN NUMBER
IS
OLD_COUNT NUMBER(5) DEFAULT 0;
NEW_COUNT NUMBER(5) DEFAULT 0;
BEGIN
SELECT
COUNT(EMP_ID) INTO OLD_COUNT
FROM
OLD_DEPT
WHERE
EID = EMP_ID
AND DEPT_STAT='Closed';
SELECT
COUNT(EMP_ID) INTO NEW_COUNT
FROM
NEW_DEPT
WHERE
EID = EMP_ID
AND DEPT_STAT='Closed'
RETURN (NEW_COUNT + OLD_COUNT);
END;
When I use the below sql query directly it returns the correct number as 2:
SELECT FN_EMP_CNT(123) FROM DUAL;
But when I use Spring JDBC Template for retrieving the data it returns null.
int noOfEmps = jdbcTemplate.queryForObject("SELECT FN_EMP_CNT(?) FROM DUAL", new Object[] { empID}, Integer.class);
The most probable cause is that you use a wrong order of parameters, see Javadoc queryForObject
queryForObject(java.lang.String sql, java.lang.Class<T> requiredType, java.lang.Object... args)
Query given SQL to create a prepared statement from SQL and a list of
arguments to bind to the query, expecting a result object.
So use first the required return type followed by the parameter
This works for my fine
sql = 'SELECT FN_EMP_CNT(?) FROM DUAL'
res = jdbcTemplate.queryForObject(sql, Integer.class, 4)
HTH
I'm newbie in Java and PLSQL. I've build this procedure in PLSQL:
PROCEDURE getLogs (
p_idcontract IN NUMBER,
p_iduser IN NUMBER,
o_logs OUT VARCHAR2
)
IS
BEGIN
SELECT logData INTO o_logs
FROM SERVICELOG
WHERE IDCONTRACT= p_idcontract
AND IDUSER= p_iduser;
END getLogs;
If script detect several rows, return to the Java class who launch it this message:
ORA-01422: exact fetch returns more than requested number of rows
Please, how I can return an hashmap or similar, ready to be outputted to Java? Thanks.
I would use ref cursor as an output parameter then build map inside java program. https://oracle-base.com/articles/misc/using-ref-cursors-to-return-recordsets
You can also define a user type in oracle that will be something like Java Array.
PROCEDURE getLogs (
p_idcontract IN NUMBER,
p_iduser IN NUMBER,
p_recordset OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN p_recordset FOR
SELECT logData
FROM SERVICELOG
WHERE IDCONTRACT= p_idcontract
AND IDUSER= p_iduser;
END getLogs;
Java code:
CallableStatement stmt = conn.prepareCall("BEGIN getLogs(?, ?, ?); END;");
stmt.setInt(1, 0);
stmt.setInt(2, 0);
stmt.registerOutParameter(3, OracleTypes.CURSOR);
stmt.execute();
ResultSet rs = ((OracleCallableStatement)stmt).getCursor(3);
while (rs.next()) {
;
//here build your Map, list or whatever you want
}
I am trying to call a stored procedure.
A stored procedure is proven by tests in the database and executed
CREATE OR REPLACE FUNCTION statapi.pui_src_ter(p_src_ter_id id_t, p_aname name_t, p_adesc desc_t, p_sortord sortord_t)
RETURNS integer AS
$BODY$
DECLARE
afected_rows integer := 0;
BEGIN
update statdwh.src_ter
set aname = p_aname,
adesc = p_adesc,
sortord = p_sortord,
actdt = current_timestamp
where src_ter_id = p_src_ter_id;
get diagnostics afected_rows = row_count;
if (afected_rows = 0) then
insert into statdwh.src_ter(src_ter_id, aname, adesc, sortord, actdt)
values (p_src_ter_id, p_aname, p_adesc, p_sortord, current_timestamp)
returning src_ter_id into p_src_ter_id;
get diagnostics afected_rows = row_count;
end if;
return afected_rows;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION statapi.pui_src_ter(id_t, name_t, desc_t, sortord_t)
OWNER TO postgres;
the call itself
public void storedProcedureCall() throws ClassNotFoundException, SQLException {
CallableStatement cst = connection.prepareCall("{call statapi.pui_src_ter(?,?,?,?)}");
cst.setInt(1, 11);
cst.setString(2, "aname_att");
cst.setString(3, "adesc_att");
cst.setInt(4, 222);
ResultSet result3 = cst.executeQuery();
while (result3.next()){
System.out.println(result3.getString(1));
}
cst.execute();
}
returns "1" as expected, since modified one record, but in the database (I look through pgAdmin) record does not appear
What am I doing wrong?
Senior fellow replied simply "add connection.commit();"
I have a stored procedure in SQL Server 2012 which has a few parameters including table type parameters as well, as SQL server 2012 does not support table type parameters i wrote another stored procedure by setting default values for this table type parameter and having only varchar as parameter for the new procedure
DECLARE #pTempTable TABLE(
region varchar(max),
country varchar(max),
username varchar(max),
firstname varchar(max),
lastname varchar(max),
accessform varchar(max),
accessmodule varchar(max),
adate varchar(max),
atime varchar(max)
)
BEGIN
DECLARE #pTestFromDate DATETIME = '2008/01/01', #pTestToDate DATETIME = '2014/12/31'
DECLARE #pCountryIds GuidsTableType
INSERT #pCountryIds VALUES(NULL)
DECLARE #pRegionIds GuidsTableType
INSERT #pRegionIds VALUES(NULL)
DECLARE #pUserId UNIQUEIDENTIFIER = NULL
DECLARE #pModuleId UNIQUEIDENTIFIER = NULL
insert into #pTempTable exec usp_rpt_UserAudit
#RoleName = #pRoleName
,#pCountryIds=#pCountryIds
,#pRegionIds=#pRegionIds
,#pUserId=#pUserId
,#pModuleId=#pModuleId
,#pFromDate=#pTestFromDate
,#pToDate=#pTestToDate
SELECT * from #pTempTable
END
GO
I have written a java code to execute this stored procedure, i am able to establish the connection, but the execute() method always returns false. The java code is as below
String finalSql = "{ call usp_rpt_sprocexecution(?) } ";
CallableStatement cs = connection.prepareCall(finalSql);
cs.setString(1, "Super Administrator");
System.out.println(cs.execute());
int c=0;
while(!((cs.getMoreResults() == false) && (cs.getUpdateCount() <= 1))){
System.out.println(c++);
ResultSet rs = cs.getResultSet();
System.out.println(rs.getString(1));
}
When i execute this same stored procedure in Management Studio it returns correct result table.
The procedure returns messages like 1 row(s) affected which is treated as a Stored Procedure output in java hence subsiding the original result.
The Simple trick was to add SET NOCOUNT ON at the start of the Stored Procedure so that it does not return such messages and hence returns the actual output.
I have a procedure I'm calling using a JDBC callable statement. The first parameter, v_type, has a default value I want to use. The proc/code is simplified.
PROCEDURE select_type(v_type IN VARCHAR2 DEFAULT 'All',
cv_1 OUT SYS_REFCURSOR)
AS
BEGIN
IF (v_type = 'All')
THEN
OPEN cv_1 FOR
SELECT DISTINCT TYPE,
FROM type_source;
ELSE
IF (v_type = 'NotAll')
THEN
OPEN cv_1 FOR
SELECT DISTINCT type, desc,
FROM OTHER_TYPE_SOURCE;
END IF;
END;
This is the code I attempted, assuming null would trigger the default.
callablestatement = connection.prepareCall("{ CALL select_type(?,?) } ") ;
callablestatement.setString(1, null);
callablestatement.registerOutParameter(2, OracleTypes.CURSOR);
callablestatement.execute();
resultset = (ResultSet)callablestatement.getObject(2);
The last line .getObject() throws a cursor closed exception, presumably, due to the null parameter not matching the IF structure in the procedure and the cursor never being opened.