There are a lot of examples over the net which describe how to call a stored procedure using Hibernate, however, when using Spring, the picture changes a bit.
I have a stored procedure in MySQL which I want to call:
in SQL I need to write the following:
CALL inrange(32.342324,32.234234);
It returns a row with the following: `{INT},{INT},{FLOAT}`
With Spring, I use the HibernateTemplate way of executing hibernate operations, I know that some of you won't like it, but this is the how the project was when I started, and I'm not so eager changing it, maybe in the future...
Currently, I have the following code in Java, which tries to call the procedure:
List<Object[]> resultset = hibernateTemplate
.findByNamedQuery("inrange",
person.getAddress().getLatitude(),
person.getAddress().getLongitude());
When I run it, I get the following Hibernate exception:
org.springframework.orm.hibernate3.HibernateSystemException:
Named query not known: inrange;
I figured that this is happening duo the fact that I didn't declare the stored procedure in hibernate.
My question is:
how do I declare it ?
Is there a special way of declaring it in the Spring's application context file ?
You can call native sql queries within hibernate.
Look at this link:
http://www.mkyong.com/hibernate/how-to-call-store-procedure-in-hibernate/
Btw if you want to call stored procedures you could simply use a Spring JdbcTemplate.
Notice that an hibernate extension can fit to your needs:
http://www.hibernatespatial.org/
You're confusing Hibernate's named queries with MySQL's stored procedures.
If you want to call the MySQL stored proc, there is no benefit to doing so through Hibernate's API. I recommend you use Spring's JdbcTemplate to perform the query.
If you absolutely must use Hibernate, something like this should work:
SQLQuery query = hibernateTemplate.getCurrentSession()
.createSQLQuery("SELECT inrange(:latitude, :longitude)";
query.setDouble("latitude", ...);
query.setDouble("longitude", ...);
List<Object[]> result = query.list(); // requires casting for generics
You need to add the named query to your hibernate mapping file.
Can you share your hibernate mapping file? You can find some samples here.
Along with the previous link you can go through this also.
It will be easier if you can share the POJO, hibernate mapping and the procedure you are using.
This blog will be of help for you. I hope you will not have any problem with using the getHibernateTemplate().execute(HibernateCallback) method.
You can use JPA as Spring supports it either in Core or Spring Data.
Calling the stored procedure can be done using the StoredProcedureQuery as follows:
StoredProcedureQuery query = entityManager
.createStoredProcedureQuery("count_comments")
.registerStoredProcedureParameter(
"postId", Long.class, ParameterMode.IN)
.registerStoredProcedureParameter(
"commentCount", Long.class, ParameterMode.OUT)
.setParameter("postId", 1L);
query.execute();
Long commentCount = (Long) query
.getOutputParameterValue("commentCount");
Related
Is it possible to use JOOQ to form a simple string query without creating factory using connection as compile time check is not required?
I dont want to establish the connection first and generate the classes
Yes you can execute SQL as strings. But you will loose all benefits from code completion will writing queries and the type safety and this is the many advantage of jOOQ over using plain JDBC.
// Create a Query object and execute it:
Query query = create.query("DELETE FROM BOOK");
query.execute();
// Create a ResultQuery object and execute it, fetching results:
ResultQuery<Record> resultQuery = create.resultQuery("SELECT * FROM BOOK");
Result<Record> result = resultQuery.fetch();
Please also checkout the documentation. https://www.jooq.org/doc/3.13/manual-single-page/#sql-execution
There are few example out there but non of them are very clarified (or on old version).
I want to call MySQL procedure and check the return status (in rails 4.2). The most common method I saw is to call result = ActiveRecord::Base.connection.execute("call example_proc()"), but in some places people wrote there is prepared method result = ActiveRecord::Base.connection.execute_procedure("Stored Procedure Name", arg1, arg2) (however it didn't compiled).
So what is the correct way to call and get the status for MySQL procedure?
Edit:
And how to send parameters safly, where the first parameter is integer, second string and third boolean?
Rails 4 ActiveRecord::Base doesn't support execute_procedure method, though result = ActiveRecord::Base.connection still works. ie
result = ActiveRecord::Base.connection.execute("call example_proc('#{arg1}','#{arg2}')")
You can try Vishnu approach below
or
You can also try
ActiveRecord::Base.connections.exec_query("call example_proc('#{arg1}','#{arg2}')")
here is the document
In general, you should be able to call stored procedures in a regular where or select method for a given model:
YourModel.where("YOUR_PROC(?, ?)", var1, var2)
As for your comment "Bottom line I want the most correct approach with procedure validation afterwards (for warnings and errors)", I guess it always depends on what you actually want to implement and how readable you want your code to be.
For example, if you want to return rows of YourModel attributes, then it probably would be better if you use the above statement with where method. On the other hand, if you write some sql adapter then you might want to go down to the ActiveRecord::Base.connection.execute level.
BTW, there is something about stored proc performance that should be mentioned here. In several databases, database does stored proc optimization on the first run of the stored proc. However, the parameters that you pass to that first run might not be those that will be running on it more frequently later on. As a result, your stored-proc might be auto-optimized in a "none-optimal" way for your case. It may or may not happen this way, but it is something that you should consider while using stored procs with dynamic params.
I believe you have tried many other solutions and got some or other errors mostly "out of sync" or "closed connection" errors. These errors occur every SECOND time you try to execute the queries. We need to workaround like the connection is new every time to overcome this. Here is my solution that didn't throw any errors.
#checkout a connection for Model
conn = ModelName.connection_pool.checkout
#use the new connection to execute the query
#records = conn.execute("call proc_name('params')")
#checkout the connection
ModelName.connection_pool.checkin(conn)
The other approaches failed for me, possibly because ActiveRecord connections are automatically handled to checkout and checking for each thread. When our method tries to checkout a connection just to execute the SP, it might conflict since there will be an active connection just when the method started.
So the idea is to manually #checkout a connection for the model instead of for thread/function from the pool and #checkin once the work is done. This worked great for me.
I am using EF 4.3 Code first with MySQL database. I am having problem executing stored procedure on the server. The code looks like as follows:
ExecuteFunction<SomeResultType>("StoredProcName",parameter1)
I am getting error The FunctionImport 'StoredProcName' could not be found in the container 'CodeFirstContainer'.
I have tried giving name as CodeFirstContainer.StoredProcName but no luck. Anyone have any idea about this problem?
Thanks,
Have you imported the stored procedure to your EDMX and created function import for it? ExecuteFunction is dependent on EDMX and function imports. If you are using code-first you cannot use it. You must use ExecuteStoreQuery / ExecuteStoreCommand on ObjectContext instance or SqlQuery / ExecuteSqlCommand on Database instance accessible through DbContext instance.
I have implemented Change Tracking (http://msdn.microsoft.com/en-us/library/cc280462.aspx) on some tables I am using Linq2Sql on.
As a part of this I need to add the below SQL to the start of the update statements generated.
DECLARE #originator_id varbinary(128);
SET #originator_id = CAST('SyncService' AS varbinary(128));
WITH CHANGE_TRACKING_CONTEXT (#originator_id)
....generated statements....
....
....
I know I can create stored procedures and manually map the fiels but I would like to avoid this if possible.
does anyone know a way to override and edit the SQL on SubmitChanges()?
You can override the Update method by implementing partial classes on your datacontext that LINQ to SQL will call instead. Just give it the signature:
partial void UpdateClassName(ClassName instance)
You can also pass through to what it would normally do using:
ExecuteDynamicInsert(instance);
Unfortunately there is no mechanism just to get the intended SQL back for inserts/update/deletes (you can get SELECT statements with GetCommand on the DataContext)
This page from SQL Server 2008 BOL, talks about CLR Stored Procedures and has a section labelled, "Table-Valued Parameters", which talks about how they can be advantageous. That's great - I'd love to use TVPs in my CLR procs, but unfortunately this seems to be the only reference in the universe to such a possibility, and the section doesn't describe what the syntax would be (nor does the further information linked at the end of the paragraph)
Sure, I can easily find descriptions of how to use TVPs from T-SQL procs, or how to do CLR procs in general. But writing a CLR proc that takes a TVP? Nothing. This is all highly unusal since the passing of multi-row data to a stored proc is a popular problem.
This leads me to wonder if the presence of the section on that page is an error. Somebody please tell me it's not and point me to more info/ examples.
[EDIT]
I was about to post this to one of the MS forums too when I came across this, which seems to be the final nail in the coffin. Looks like it can't be done.
I can find a lot more references. However, these are all for passing table-valued parameters to TSQL procedures, so that's of little use.
However, I've come to the conclusion that it's impossible. First, there is the list of mappings between CLR and SQL types. For table types there is no mapping, so the following does not work, for example:
[SqlProcedure]
public static void StoredProcedure(DataTable tvp, out int sum)
{
return 42;
}
and then
CREATE TYPE MyTableType AS TABLE
(
Id INT NOT NULL PRIMARY KEY,
[Count] INT NOT NULL
)
GO
CREATE ASSEMBLY ClrTest FROM '<somePath>'
GO
CREATE PROCEDURE ClrTest
AS EXTERNAL NAME ClrTest.StoredProcedures.StoredProcedure
GO
Whatever type you try (DataTable, DbDataReader, IEnumerable), the CREATE PROCEDURE call keeps generating an error 6552: CREATE PROCEDURE for "ClrTest" failed because T-SQL and CLR types for parameter "#tvp" do not match.
Second, the documentation on the page you linked to says: A user-defined table type cannot be passed as a table-valued parameter to, or be returned from, a managed stored procedure or function executing in the SQL Server process.
I can not seem to find anywhere how to create a user defined table type in C#, but this also seems to be a dead end.
Maybe you can ask your question somewhere on a Microsoft forum. It's still odd that they mention table-valued parameters on the CLR sproc page but never explain how to implement this. If you find any solution, I'd like to know.
You can use a temporary table created and populated before you call the procedure and read the table inside the clr procedure.
The solution is to serialize your tabular data into a Json-formatted string then pass the string into your CLR proc. Within your clr proc or function you would parse the json to an IEnumerable, list, or tabular object. You may then work with the data as you would any other type of tabular data.
I have written some utilities capable of serializing any sql table into a Json formatted string. I would be happy to share them with anyone providing their e-mail address. Phil Factor has written a nice T-SQL Json parser he called parseJson. I have adapted his solution to the clr which performs much faster. Both accept a Json formatted string and produce a table from the string. I also have a variety of Json utilities I employ with both T-SQL and the CLR capable of serializing, parsing, inserting, deleting, and updating Json formatted strings stored in sql columns.
If you use C# (as opposed to VB, which lacks custom iterators) you can write ADO.NET code to invoke ExecuteNonQuery() and run a stored procedure with a SqlDbType.Structured parameter (i.e., a TVP).
The collection passed as the value of the TVP must implement IEnumerable<SqlDataRecord>. Each time this IEnumerable's yield return is executed, a SqlDataRecord “row” is pipelined to the "table" parameter.
See this article for details.
Whilst it looks like passing tables directly to CLR procedures is currently impossible, I got a result, albeit sub optimal by:
defining a TSQL table valued UDT FooTable
defining a TSQL function which takes FooTable as a param and returns XML using FOR XML EXPLICIT
passing the resultant XML to the CLR function/procedure instead of the table itself
Not ideal, but it gets a bit closer.