I have a stored procedure that calls like this:
CREATE OR REPLACE TYPE numbers_tbl IS TABLE OF NUMBER;
declare
vess_ids numbers_tbl := numbers_tbl(91,250,251,48,339,145,172,202,174);
rez Number(19,0);
begin
dev4.limits_get_comp_catch(vess_ids, rez);
dbms_output.put_line(rez);
end;
and I'm looking for a way to call it from my java application using hibernate.
ProcedureCall call = getCurrentSession().createStoredProcedureCall("limits_get_comp_catch");
Kinda stuck on how to pass a List<Long> to the procedure. Any ideas?
Related
I was running a stored procedure with Springs SimpleJdbcCall like this:
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate).withProcedureName("example_proc");
jdbcCall.execute();
// do other stuff on other subsystems
// the sysout below is just an example - the real scenario was somewhat different
System.out.println("Supposedly after the end of the stored procedure call");
The stored procedure was running for a long time, and it was overlapped with the stuff that was supposed to happen after that.
The stored procedure was written in Microsoft's SQL Server dialect, and looked like this:
CREATE PROCEDURE example_proc
AS
BEGIN
INSERT INTO example_table_1 SELECT * FROM example_table_2
UPDATE example_table_1 SET col1 = 'a' WHERE ...
END
The question is: how to make sure the SimpleJdbcCall waits until the stored procedure finishes?
There is a hack for this: make the stored procedure return something, and then retrieve it in the jdbc call.
The is the stored procedure:
CREATE PROCEDURE example_proc
AS
BEGIN
INSERT INTO example_table_1 SELECT * FROM example_table_2
UPDATE example_table_1 SET col1 = 'a' WHERE ...
-- this is just a hack for running it synchronously:
SELECT 1 AS success
END
Now that it returns something, the jdbc call can wait for that:
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
.withProcedureName("example_proc").
returningResultSet("success", new SingleColumnRowMapper<Integer>());
Map<String, Object> map = jdbcCall.execute();
#SuppressWarnings("unchecked")
List<Integer> storedProcedureResults = (List<Integer>) map.get(success);
int result = storedProcedureResults.get(0);
// I did something to the result. I am not sure if this is really necessary.
// But I was worried if the jvm or javac would optimize the dead code.
// I returned the value from a method. Printing it should also be enough.
System.out.println(result);
I am trying to execute a Stored Procedure which updates a column and retrieves the filename from the same table after updating
StoredProcedure:
CREATE DEFINER=`test`#`%` PROCEDURE `update_count`(
IN in_testID VARCHAR(64),
OUT out_FileName VARCHAR(100),
OUT out_Message VARCHAR(100))
BEGIN
UPDATE files SET count=count+1 WHERE testID=in_testID;
SELECT FileName INTO out_FileName FROM files WHERE testID = in_testID;
SET out_Message = 'File updated uccessfully';
END
JavaCode to execute this StoredProcedure:
Query query = session.createSQLQuery("CALL update_count(:in_testID, #out_FileName, #out_Message)").addEntity(FilesBean.class)
.setParameter("in_testID",body.getTestId());
query.executeUpdate();
Updated the query.executeUpdate() with query.list(). But the line returning a error ResultSet is from UPDATE. No Data
I need to fix this with using the createSQLQuery
The easiest way to do that is return the out parameter as part of the returning parameters (relevant only if you have access to the store procedures).
just add a store procedure like the following one
create procedure myProcedure_only_in_prams (
in in_Id int)
begin
call myProcedure(in_id,#out_Id) ;
select #out_id
END;
after done that it quite simple to use it with Hibernate in the following way
Query query = session.createSQLQuery(
"CALL myProcedure_only_in_parms (:in_Id)")
.setParameter("in_id", 123);
List result = query.list();
The result contains the out parameter, if you want return multiply parameters you can add it by doing select #parm1,#parm2,... ,#parmn
Hope it helped
I'm trying to use a table-valued parameter for a stored procedure we're calling using Hibernate's Session.createSQLQuery.
I have created a type and stored procedure in SQL:
CREATE TYPE StringListType AS TABLE
(
StringText NVARCHAR(256)
)
CREATE PROCEDURE [dbo].[TestStringListType]
(
#stringList StringListType READONLY
)
AS
SELECT * FROM #stringList
I can use this in SQL with:
BEGIN
Declare #StringListTemp As StringListType
insert INTO #StringListTemp (StringText)
values ('foo'), ('bar'), ('baz')
EXEC TestStringListType #StringListTemp
END
What I would like to do in Java is something like:
String fakeQueryStr = "call TestStringListType :list";
SQLQuery fakeQuery = getSession().createSQLQuery(fakeQueryStr);
ArrayList<String> data = Lists.newArrayList("foo", "bar", "baz");
fakeQuery.setParameter("list", data);
return fakeQuery.list();
Neither setParameter or setParameterList work here of course. How do I map my list of Strings to this type to use as a parameter?
I was unable to find a solution for this problem as written. My work-around was to copy the entirety of the stored procedure into a string in Java. In the above example, that would mean that I replaced:
String fakeQueryStr = "call TestStringListType :list";
with
String fakeQueryStr = "SELECT * FROM :list";
In my actual code, this was undesirable, because the stored procedure was a significantly longer set of statements, but it does still work when wrapped in BEGIN and END within the string.
I have a function I created in my PostgreSQL DB that I want to call using JPA 2.1's StoredProcedureQuery method.
Here is my PostgreSQL query:
CREATE OR REPLACE FUNCTION get_values(date text) returns refcursor
AS $$
DECLARE tuples refcursor;
BEGIN OPEN tuples FOR
SELECT user, COUNT(*)
FROM my_table
WHERE date_ = date
GROUP BY user;
return tuples;
END;
$$
LANGUAGE plpgsql
This is just a simple query to count users on a particular day. This is just a demo query to test how the StoredProcedureQueries work. And in fact, it works just fine when used via postgreSQL alone.
Now, let's try and call this using JPA 2.1 and in Javaland:
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("get_values");
storedProcedure.registerStoredProcedureParameter(2, String.class, ParameterMode.IN);
storedProcedure.registerStoredProcedureParameter(1, Object.class, ParameterMode.REF_CURSOR);
storedProcedure.setParameter(2, "2015-02-01");
storedProcedure.execute();
When I do this, I get back the following exception:
org.hibernate.HibernateException: PostgreSQL supports only one REF_CURSOR parameter, but multiple were registered
There is only a single ref cursor declared! In fact, if I just register the single REF_CURSOR parameter and hardcode in a value for my Postgresql function for the WHERE date_ = date, this call works just fine.
So it would seem adding any additional parameters to a storedprocedurequery with a ref_cursor breaks the functionality. Alone, the ref_cursor parameters works fine.
Anybody see why this would happen?? Why is it that adding parameters to the StoredProcedureQuery for my PostgreSQL function breaks it?
Example of when it works:
CREATE OR REPLACE FUNCTION get_values(date text) returns refcursor
AS $$
DECLARE tuples refcursor;
BEGIN OPEN tuples FOR
SELECT user, COUNT(*)
FROM my_table
WHERE date_ = '2015-02-01'
GROUP BY user;
return tuples;
END;
$$
LANGUAGE plpgsql
and in javaland:
StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("get_values");
storedProcedure.registerStoredProcedureParameter(1, Object.class, ParameterMode.REF_CURSOR);
storedProcedure.execute();
Short answer: Reverse the order of your two calls to registerStoredProcedureParameter():
storedProcedure.registerStoredProcedureParameter(1, Object.class, ParameterMode.REF_CURSOR);
storedProcedure.registerStoredProcedureParameter(2, String.class, ParameterMode.IN);
Long answer: I did some digging in the Hibernate source code for Postgress callable statement support, and found that each registerStoredProcedureParameter() call creates a ParameterRegistrationImplementor instance that gets tacked into a list and passed around. You'll note that this class stores the position of the parameter, which is independent of its position within the list.
Later, this list is analyzed and assumes that the REF_CURSOR parameter will be first in line, and throws your error message if a REF_CURSOR parameter is not first, regardless of what the parameter number is.
Not a very bright way of doing things (IMHO), but at least the workaround is easy: if you swap the order of your calls, you should be fine.
DELIMITER //
CREATE PROCEDURE temp ( empId INT)
BEGIN
DECLARE var_etype VARCHAR(36);
SELECT
emptype = QOUTE(emptype)
FROM
dms_document
WHERE
id = empid;
SELECT
emptype,
CASE
WHEN emptype = 'P' THEN doctype
ELSE 'No Documents required'
END
FROM
dms_report
WHERE
pilot = 1;
End//
DELIMITER ;
I have created this procedure successfully but when I try to call it, I am getting error 1305 the function database.temp does not exist. I am trying to call using this statement:
SET #increment = '1';
select temp( #increment)
but I get Error, please tell me where I made mistake.
This is how you call it, use use the keyword call and then procedure's name
call procedureName(params);
in call of making an string
String sqlString = "procedureName("+?+")"; //in case of Integers
String sqlString = "procedureName('"+?+"')";//in case of Integers
bring the parameter in prepared statement.
MySQL's documentation on Using JDBC CallableStatements to Execute Stored Procedures explains the necessary steps quite well.
This is what your java code needs to look like:
CallableStatement cStmt = conn.prepareCall("{call temp(?)}");
cStmt.setInt(1, 42); //set your input parameter, empId, to 42.
If you want to work with the rows returned by your stored procedure's query in your Java code, you're also going to need to create an OUT parameter as noted in MySql's documentation page titled, CALL Syntax:
CALL can pass back values to its caller using parameters that are
declared as OUT or INOUT parameters
In order to call your stored procedure from MySQL workbench, use the CALL command. You can call stored procedure by directly setting values for each of the parameters:
SET #increment = 1;
CALL temp(#increment)
Then you simply use the SELECT statement to return the value of your output parameter
SELECT #outParameter
With help setting your output parameters, please read the article MySQL Stored Procedure - SELECT - Example.
Your stored procedure is syntactically wrong, and as mentioned in the comments, you're not using the stored procedure functionality for it's intended use. It's intended to be used for data manipulation not for querying. You should instead consider turning your procedure into a series of prepared statements.
Please let me know if you have any questions!