JPA call Store Procedure returned wrong result - jpa

I am using JPA native query to call a stored procedure and map the return result to a class
createNativeQuery(String sqlString, Class resultClass);
Here sqlString is a stored procedure in this format:
{call storeProcedureName parameter1, paramter2, parameter3}
I noticed that when one of the parameter contains a forward slash (/), the result result will be wrong. Has any body encountered this problem before and how to solve it? thanks
I am using EclipseLink and glassfish server.

Are you in-lining the parameters into your SQL, or using parameters on your query? You should use parameters on your query, in-lining parameters into SQL is very bad (can lead to SQL injection attacks).
See,
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/Native#Parameters

Related

EFCore 3.1 FromSqlRaw is not working and throwing a bizarre error message

I have the most bizarre issue with EF Core 3.1. In EF Core 2.2 I used to be able to execute stored procedures. I see there is a breaking change in the documentation but, I am following the documentation exactly and it is not working. I have no nulls anywhere in the returned data. The NoticeOfInspection object matches the returned data exactly. What on Earth did they change that this is not working?
var data = _dbContext.NoticeOfInspections.FromSqlRaw("EXEC dbo.NewReportApp_NoticeOfInspection {0}", FacilityId).Single();
The error message is not helpful at all. First with the above line, it says, "InvalidOperationException: FromSqlRaw or FromSqlInterpolated was called with non-composable SQL and with a query composing over it. Consider calling AsEnumerable after the FromSqlRaw or FromSqlInterpolated method to perform the composition on the client side."
What?
So, I add AsEnumerable and then it throws, "InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'."
What on Earth have they done. This is not intuitive at all.
FromSqlRaw or FromSqlInterpolated was called with non-composable SQL
The non-composable SQL is the one which cannot be converted to subquery select * from (your_sql). Calling SP (EXEC …) is one of the non-composable constructs.
and with a query composing over it
Non query returning LINQ operators like Single, First, Count, Max, Sum etc. require composing over the provided SQL query, for instance select count * from (your_query).
You can read more about it in Raw SQL queries - Composing with LINQ documentation topic, which also contains the "calling SP" and other limitations/restrictions:
Composing with LINQ requires your raw SQL query to be composable since EF Core will treat the supplied SQL as a subquery. SQL queries that can be composed on begin with the SELECT keyword. Further, SQL passed shouldn't contain any characters or options that aren't valid on a subquery, such as:
A trailing semicolon
On SQL Server, a trailing query-level hint (for example, OPTION (HASH JOIN))
On SQL Server, an ORDER BY clause that isn't used with OFFSET 0 OR TOP 100 PERCENT in the SELECT clause
SQL Server doesn't allow composing over stored procedure calls, so any attempt to apply additional query operators to such a call will result in invalid SQL. Use AsEnumerable or AsAsyncEnumerable method right after FromSqlRaw or FromSqlInterpolated methods to make sure that EF Core doesn't try to compose over a stored procedure.
With that being said, inserting AsEnumerable() before Single() should really work.
The new exception you are getting is either EF Core bug or data type mapping issue (either you are passing int to string parameter, or SP is returning int for string class property). You need to examine the exception stack trace and/or compare your SP parameter and column types to FacilityId argument type and NoticeOfInspection class property types/mappings.

JDBI query when using type annotations?

I'm writing a Dropwizard app that needs to connect to the database, and using SQL objects to query the DB, per the Dropwizard docs.
The issue I'm running into is when my query is using a type specifier (::) being confused for a binding variable. Something like
SELECT
(a,
b,
c)::user_type
FROM ...
WHERE id = :id
The parser is reading ::user_type as a parameter placeholder. When I've escaped them with \, it says the query is not returning any rows, but if I run the query through psql, it does, so I'm guessing it's not so simple. Any help would be appreciated.
Thanks! :D
The easiest solution is to just use the SQL-standard CAST syntax not the PostgreSQL extension :: syntax.
CAST (c AS user_type)

Calling Postgres function using QueryDSL

I have a package with similarity functions installed on my Postgres DB. I was calling them using pure SQL on a JDBC, and it was working as expected.
Now I'm trying to refactor my code to use QueryDSL. The first step of the similarity function is set a limit, between 0 and 1, so that only results above that given threshold are returned. I'm trying this way:
NumberExpression<Float> sim = Expressions.numberTemplate(Float.class, "set_limit({0})", "0.2");
query.singleResult(sim);
I get the following error:
java.lang.IllegalArgumentException: No joins given
I know I haven't passed an EntityPath. If I try and use any EntityPath, I get the error:
`[[IllegalStateException: No data type for node: org.hibernate.hql.internal.ast.tree.MethodNode
\-[METHOD_CALL] MethodNode: '('
+-[METHOD_NAME] IdentNode: 'set_limit' {originalText=set_limit}
\-[EXPR_LIST] SqlNode: 'exprList'
\-[NAMED_PARAM] ParameterNode: '?' {name=1, expectedType=null}
]]`
After that, I'd call another DB function, but I guess the solution would be the same.
Is this possible with QueryDSL?
set_limit isn't valid JPQL, that's why Hibernate throws an exception. Querydsl JPA maps internally to JPQL, and Querydsl SQL to SQL.
If you need SQL expressivity, like in this case, you will need to use Querydsl SQL instead.

JPA: How to call a stored procedure

I have a stored procedure in my project under sql/my_prod.sql
there I have my function delete_entity
In my entity
#NamedNativeQuery(name = "delete_entity_prod",
query = "{call /sql/delete_entity(:lineId)}",
and I call it
Query query = entityManager.createNamedQuery("delete_entity_prod")
setParameter("lineId",lineId);
I followed this example: http://objectopia.com/2009/06/26/calling-stored-procedures-in-jpa/
but it does not execute the delete and it does not send any error.
I haven't found clear information about this, am I missing something? Maybe I need to load the my_prod.sql first? But how?
JPA 2.1 standardized stored procedure support if you are able to use it, with examples here http://en.wikibooks.org/wiki/Java_Persistence/Advanced_Topics#Stored_Procedures
This is actually they way you create a query.
Query query = entityManager.createNamedQuery("delete_entity_prod")
setParameter("lineId",lineId);
To call it you must execute:
query.executeUpdate();
Of course, the DB must already contain the procedure. So if you have it defined in your SQL file, have a look at Executing SQL Statements from a Text File(this is for MySQL but other database systems use a similar approach to execute scripts)
There is no error shown because query is not executed at any point - just instance of Query is created. Query can be executed by calling executeUpdate:
query.executeUpdate();
Then next problem will arise: Writing some stored procedures to file is not enough - procedures live in database, not in files. So next thing to do is to check that there is correct script to create stored procedure in hands (maybe that is currently content of sql/my_prod.sql) and then use that to create procedure via database client.
All JPA implementations do not support calling stored procedures, but I assume Hibernate is used under the hood, because that is also used in linked tutorial.
It can be the case that current
{call /sql/delete_entity(:lineId)}
is right syntax for calling stored procedure in your database. It looks rather suspicious because of /sql/. If it turns out that this is incorrect syntax, then:
Consult manual for correct syntax
Test via client
Use that as a value of query attribute in NamedNativeQuery annotation.
All that with combination MySQL+Hibernate is explained for example here.

How are multiple result sets accessed in slick?

How does Slick handle a query that returns multiple result sets?
For example, if I wanted to retrieve information about a table using sp_help someTableName
Which would return a number of result sets. I can get the first result set, simply using scala.slick.jdbc.StaticQuery.queryNA[Tuple4[String, String, String,String]]("sp_help tblInbox_membership").first()
How do I get the second result set?
You must be using Sybase or maybe SqlServer.
I'm not familiar with Slick (yet), but the way to access subsequent ResultSets from a statement in JDBC is to call Statement.getMoreResults(), then if that succeeds Statement.getResultSet(). Slick gives you a Statement object with Session.withStatement, so you could at least use the JDBC api to get your resultsets, or feed the ResultSet to Slick if there is a way to do that.