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.
Related
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 had got the solution for getting columns of a synonym table when browsed stackoverview
DatabaseMetaData.getColumns returning an empty ResultSet for synonyms
But could not get any reference for getting function params dynamically in Java Code for a function synonym in Database. Need suggestion
...a function, say func1() in schema1 is created as synonym function as
test_func() in schema2
You can use the data dictionary views to get the real function name, function owner and even procedure parameters.
Here you can get the information re the synonym - the owner, real function name:
select table_owner, table_name, table_owner||'.'||table_name full_function_name
from all_synonyms
where owner in ('PUBLIC',user)
and synonym_name = 'FUNC1'
Having defined the owner of the function (schema2 name in your case) and the real function name - you can extract the parameters from db query:
select *
from all_arguments
where owner = _table_owner_
and object_name = _table_name_
Hope this helps.
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?
Is there any easy way to get a completed SQL statement after parameter substitution?
I am using elasticsearch-sql to query elastic search with sql statements, however I have to submit the query with all the parameters substituted.
I tried Hibernate Query getQueryString, but the parameter substitution is not happening for those sql strings.
The following sql string is produced:
"SELECT * FROM USER WHERE NAME=? AND SURNAME=?"
rather than:
"SELECT * FROM USER WHERE NAME='Selva' AND SURNAME='Esra'
Appreciate any better idea/thoughts?
1. Named parameters
This is the most common and user friendly way. It use colon followed by a parameter name (:example) to define a named parameter. See examples…
String hql = "SELECT * FROM USER WHERE NAME= :userName AND SURNAME= :surName";
Query query = session.createQuery(hql);
query.setParameter("userName ", "userName");
query.setParameter("surName", "SurName");
List results = query.list();
An object-oriented representation of a Hibernate query. A Query instance is obtained by calling Session.createQuery(). This interface exposes some extra functionality beyond that provided by Session.iterate() and Session.find():
a particular page of the result set may be selected by calling setMaxResults(), setFirstResult()
named query parameters may be used
the results may be returned as an instance of ScrollableResults
Named query parameters are tokens of the form :name in the query string. A value is bound to the integer parameter :foo by calling
setParameter("foo", foo, Hibernate.INTEGER);
for example. A name may appear multiple times in the query string.
JDBC-style ? parameters are also supported. To bind a value to a JDBC-style parameter use a set method that accepts an int positional argument (numbered from zero, contrary to JDBC).
You may not mix and match JDBC-style parameters and named parameters in the same query.
2. Positional parameters
It’s use question mark (?) to define a named parameter, and you have to set your parameter according to the position sequence. See example…
Java
String hql = "from Stock s where s.stockCode = ? and s.stockName = ?";
List result = session.createQuery(hql)
.setString(0, "7277")
.setParameter(1, "DIALOG")
.list();
This approach is not support the setProperties function. In addition, it’s vulnerable to easy breakage because every change of the position of the bind parameters requires a change to the parameter binding code.
Java
String hql = "from Stock s where s.stockName = ? and s.stockCode = ?";
List result = session.createQuery(hql)
.setParameter(0, "DIALOG")
.setString(1, "7277")
.list();
Conclusion
In Hibernate parameter binding, i would recommend always go for “Named parameters“, as it’s more easy to maintain, and the compiled SQL statement can be reuse (if only bind parameters change) to increase the performance.
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!