Hibernate native sql query exception - rs cursor forward only - java

I am dealing with a legacy code that is 'not changeable' (no way to move to criteria api) and I have a little trouble with proper parameters binding. The query looks like this (MS SQL):
SELECT BRAND AS b FROM CAR WHERE (NAME LIKE :phrase OR MODEL LIKE :phrase ) AND AGE NOT IN(1997, 1998) AND (:mileage IS NULL OR MILEAGE LIKE :mileage) ORDER BY BRAND
(...)
query.setParameter("phrase", "%" + phrase + "%");
query.setParameter("mileage", mileage);
phrase is actually required, but because the mileageparameter is optional, it's done in wierd way presented above.
The problem is that with both phrase and mileage provided, It keeps giving me following error : java.sql.SQLException: ResultSet may only be accessed in a forward direction.. It works wihtout mileage parameter provided. Why I am getting this error ?
EDITED:
Running this query on db gives me no results.
I am using query.setResultTransformer(Transformers.aliasToBean(type)) as well as setting first and max result on my SQLQuery query object.
An error is when calling query.list() (used intellij evaluate expression)
shouldn't query.list() return an empty result ?
Probable answer (in that case):
It looks like setting FirstResult on the query cause that problem because - by mistake - it's a negative number.

How are you executing the SQL and then accessing the results?
It sounds like there are no results when executing the SQL with the mileage parameter and you are somehow trying to read the results anyway.
Try running the generated SQL immediately on the database and see if it returns any rows.

Related

Couchbase uses wrong indexes with N1QL parameterized queries

I have problems with understanding of way couchbase query plan works.
I use SpringData with Couchbase 4.1 and I provide custom implementation of Couchbase Repository. Inside my custom implememtnation of Couchbase Repository I have below method:
String queryAsString = "SELECT MyDatabase.*, META().id as _ID, META().cas as _CAS FROM MyDatabase WHERE segmentId = $id AND _class = $class ORDER BY executionTime DESC LIMIT 1";
JsonObject params = JsonObject.create()
.put(CLASS_VARIABLE, MyClass.class.getCanonicalName())
.put(ID_VARIABLE, segmentId);
N1qlQuery query = N1qlQuery.parameterized(queryAsString, params);
List<MyClass> resultList = couchbaseTemplate.findByN1QL(query, SegmentMembers.class);
return resultList.isEmpty() ? null : resultList.get(0);
In a result, Spring Data produces following json object represented query to Couchbase:
{
"$class":"path/MyClass",
"statement":"SELECT MyDatabase.*, META().id as _ID, META().cas as _CAS from MyDatabase where segmentId = $id AND _class = $class ORDER BY executionTime DESC LIMIT 1",
"id":"6592c16a-c8ae-4a74-bc17-7e18bf73b3f8"
}
And the problem is with performance when I execute it via Java and N1QL Rest Api or via cbq consol. For execute this query in cbq I simply replace parameters reference with exact values.
After adding EXPLAIN clause before select statement I mentioned different execution plans. Execution this query as parameterized query via Java Spring Data or N1QL Rest Api I've mentioned that query doesn't use index that I created exactly for this case. Index definiton can be found below:
CREATE INDEX `testMembers` ON MyDatabase `m`(`_class`,`segmentId`,`executionTime`) WHERE (`_class` = "path/MyClass") USING GSI;
So, when I execute query via cbq consol, Couchbase uses my idnex and query performance is very good. But, when I execute this query via N1QL rest api or Java i see that query doesn't use my index. Below you can find part of execution plan that proves this fact:
"~children": [
{
"#operator": "PrimaryScan",
"index": "#primary",
"keyspace": "CSM",
"namespace": "default",
"using": "gsi"
},
So, the question is that the right and legal behavior of couchbase query optimizer? And does it mean that query plan does not take into account real values of parameters? And have I manually put values into query string or exist eny other way to use N1Ql parameterized query with correct index selection?
EDIT
According to shashi raj answer I add N1qlParams.build().adhoc(false) parameter to parameterized N1QL query. This doesn't solve my problem, because I still have performance problem with this query. Moreover, when I print query I see that it is the same as I described earlier. So, my query still wrong analyzed and cause performance decline.
first of all you need to know how N1QL parameterized queries works query should be passed as:
String query= select * from bucketName where _class=$_class and segmentId=$segmentId LIMIT $limit ;
Now the query should be passed as:
N1QL.parameterized(query,jsonObject,N1qlParams.build().adhoc(false));
where jsonObject will have all the placeholder values.
JsonObject jsonObject=JsonObject.create().put("_class","com.entity,user").put("segmentId","12345").put("limit",100);
N1qlParams.build().adhoc(false) is optional since if you want your query to be optimized it will make use of it. It makes use of LRU where it keeps track of previously query entered and it keeps record of it so that next time it doesn't need to parse query and fetch it from previous what we call as prepared statement.
The only problem is couchbase only keeps record of last 5000 queried.
The problem in your case is caused by the fact that you have an index with 'where' clause WHERE ( _class = "path/MyClass"), and at the same time, you passing the _class as a parameter in your query.
Thus, the query optimizer analyzing the parametrized query has no idea that this query might use an index created for _class = "path/MyClass", cause it's _class = $class in a select's where. Pretty simple, right?
So, don't pass any fields mentioned in your index's 'where' as select parameters. Instead, hardcode _class = "path/MyClass" in your select in the same way you did for create index. And everything should be fine.
Here's the ticket in the couchbase issue tracking system about that.
https://issues.couchbase.com/browse/MB-22185?jql=text%20~%20%22parameters%20does%20not%20use%20index%22

connection.getMetaData() getting called for every select query in Hibernate

I am executing select queries in my java app using org.hibernate.SQLQuery. The code is as below.
Query query=session.createSQLQuery("query");
query.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List<Map<String,Object>> aliasToValueMapList=query.list();
The problem is, the oracle AWR report shows that there is another query that fires up with every select query I execute.
SELECT NULL AS table_cat, o.owner AS table_schem, o.object_name AS table_name, o.object_type AS
table_type, NULL AS remarks FROM all_objects o WHERE o.owner LIKE :1 ESCAPE '/' AND o.object_name
LIKE :2 ESCAPE '/' AND o.object_type IN ('xxx', 'TABLE') ORDER BY table_type, table_schem, table_name
Can anyone explain why this happens and how can I avoid this(I want to avoid this as this is the most CPU consuming query listed in the report)?
I could find this which exactly deals with my problem. I am going test the suggestions given in the link. I will update the result here once I figure out the right solution.
How to avoid this very heavy query that slows down the application?

JPA2 CreateQuery SQL Server Dialect

The function CreateQuery(string) in java.persistence.Query is returning a different query from what I requested.
My input string to the function is:
from Underlying where (SUBSTRING(ticker, (charindex('.', ticker) +
1), (len(ticker) - charindex('.', ticker))) in (:exchanges) order by
ticker
When I call getResultList() on the Query, I see the following sql in my log:
Hibernate: select underlying0_.id as id63_, underlying0_.updated_date
as updated2_63_, underlying0_.updated_user as updated3_63_,
underlying0_.version as version63_, underlying0_.adr as adr63_,
underlying0_.desk as desk63_, underlying0_.enabled as enabled63_,
underlying0_.forward_start_enabled as forward8_63_,
underlying0_.ticker as ticker63_, underlying0_.vol_shift_type as
vol10_63_ from underlyings underlying0_ where
(substring(underlying0_.ticker, charindex('.', underlying0_.ticker)+1)
in (?)) order by underlying0_.ticker
This is query is not a valid SQL Server 2008 query and as expected, I received an error:
SQL Error: 174, SQLState: S0001
The substring function requires 3 argument(s).
Any one know what is going on here?
FYI, I have tried the following two dialects 1) org.hibernate.dialect.SQLServer2008Dialect, and 2) org.hibernate.dialect.SQLServer2008Dialect
Issue is with function charindex. It is not available in the dialect, therefore causes incorrect mapping. Changing this to the HQL function "locate" (keeping args constant) fixed the issue. My query now works in SQL Server 2008:
...where (substring(underlying0_.ticker, charindex('.',
underlying0_.ticker)+1, len(underlying0_.ticker)-charindex('.',
underlying0_.ticker)) in (?))...
Error clearly mention that SUBSTRING() function require 3 Arguments you are passing 2. thus error is in your query.
read about SUBSTRING() Function

"ResultSet is from UPDATE: No Data" received from Java application

I am trying to use a Java application (which I do not have the source code for) to output the results of a call to a stored procedure into a text file.
This file works for other similar stored procedures in the system, but I can't seem to get it to produce anything for my new text file other than this exception:
ResultSet is from UPDATE: No Data
I've simplified the body of the stored procedure to a simple select 'Hello World!' and even that doesn't seem to be able to be written out.
Is there anything I can do within the stored procedure to produce results in a fashion that Java will accept?
I encountered this java.sql.SQLException. In my case I was running a query in this way:
String query =
"-- a classical comment " +
"select * " +
"from MYTABLE ";
ResultSet rs = conMain.createStatement().executeQuery(query);
while(rs.next()) {
//do something...
}
rs.next() throws the exception. The reason is that, due to the comments, query results to be:
"-- a classical comment select * from MYTABLE "
hence it's all commented... query is invalid! Many examples could be shown with this mistake (with the comment in the middle of the query etc.).
Solutions: add a \n at the end of each line of the query or use comments in the /*...*/ form.
I selected an older version of the driver an it worked for me.
http://dev.mysql.com/downloads/mirror.php?id=13598 (mysql-connector-java-5.0.8.zip)

NullPointerException with CallableStatement.getResultSet()

I have a stored proc in SQL Server 2005, which looks like the following (simplified)
CREATE PROCEDURE FOO
#PARAMS
AS
BEGIN
-- STEP 1: POPULATE tmp_table
DECLARE #tmp_table TABLE (...)
INSERT INTO #tmp_table
SELECT * FROM BAR
-- STEP 2: USE #tmp_table FOR FINAL SELECT
SELECT abc, pqr
FROM BAZ JOIN #tmp_table
ON some_criteria
END
When I run this proc from SQL Server Management Studio, things work fine. However, when I call the same proc from a Java program, using something like:
cs = connection.prepareCall("exec proc ?,");
cs.setParam(...);
rs = cs.getResultSet(); // BOOM - Null!
while(rs.next()) {...} // NPE!
I fail to understand why the first result set returned is NULL. Can someone explain this to me?
As a workaround, if I check cs.getMoreResults() and if true, try another getResultSet() - THIS time it returns the proper result set.
Any pointers please? (I'm using JTDS drivers, if it matters)
Thanks,
Raj
The Javadoc for getResultSet() says that it returns null "... if the result is an update count or there are no more results". It looks like your stored procedure would have an update count and a resultset, and that the getResultSet() method is (arguably) just doing what the API contract says it should do.
You could try retrieving the update count first. Otherwise, stick with your "workaround".
Kind of pointless posting an answer after the correct answer has been selected I guess.
The solution I suggest is calling
set nocount on
before the insert statement and
set nocount off
afterwards. Inserts return a resultset otherwise.

Categories

Resources