InvalidQueryException despite of correct query - java

I am using SpringBoot connceted with Hibernate and Cassandra Database. I made couple of methods using ResultSet and everything works perfect till now. I create another method, create query and then ResultSet.
String queryString = query.toString().replace("?", dayList.toString());
ResultSet rS = dataSource.executeQuery(queryString);
It throws me:
com.datastax.driver.core.exceptions.InvalidQueryException: No keyspace has been specified. USE a keyspace, or explicitly specify keyspace.tablename
Query is correct. When I execute query in database it returns me proper data.
It is wierd because I use same implementation in previous method and it works.
Here is my query:
SELECT * FROM object_action_statistics WHERE day IN ('2018-04-29','2018-04-30') AND action_id=14 AND timestamp_from>=1525099500073 AND timestamp_from<1525120897000 ALLOW FILTERING

Correct query should be like this:
SELECT * FROM KEYSPACE_NAME.object_action_statistics WHERE day IN ('2018-04-29','2018-04-30') AND action_id=14 AND timestamp_from>=1525099500073 AND timestamp_from<1525120897000 ALLOW FILTERING
I guess you forgot to put keyspace name ahead of table name.

Related

UpdateString not implemented by SQLite JDBC driver

I have a table PERSON with more than 5 millions rows and I need to update field NICKNAME on each one of them based on the field NAME inside the same table.
ResultSet rs = statement.executeQuery("select NAME from PERSON");
while(rs.next())
{
// some parsing function like:
// Nickname = myparsingfunction(rs.getString("NAME"));
rs.updateString( "NICKNAME", Nickname );
rs.updateRow();
}
But I got this error:
not implemented by SQLite JDBC driver
I'm using sqlite-jdbc-3.8.11.2.jar downloaded at https://bitbucket.org/xerial/sqlite-jdbc/downloads.
I know I could use the following SQL query:
statement.executeUpdate("update PERSONS set NICKNAME = Nickname where ID = Id");
But that would take forever and I understand updating ResultSet would be faster. So what options do I have to update the table on the fastest way? Any other driver available? Should I move out of Java?
UPDATE
I was able to find a fast solution using below syntax. The block between CASE and END was a concatenated string that I built before executing the SQL query, so I could send all updates at once.
update PERSON
set NICKNAME= case ID
when 173567 then 'blabla'
when 173568 then 'bleble'
...
when 173569 then 'blublu'
end
where ID in (173567, 173568, 173569)
As you have encountered, the SQLite JDBC driver does not currently support the updateString operation. This can be seen in the source code for this driver.
I can think of three options:
As you stated in your question, you can select the name and ID of the person and then update the person by its ID. Those updates could be done in a batch (using PreparedStatement.addBatch()) to improve performance (tutorial).
Implement the method myparsingfunction in pure SQL so that the query could become UPDATE PERSONS SET NICKNAME = some_function(NAME).
Create an user-defined function (using org.sqlite.Function), implemented in Java, and call it inside the SQL. Example, taken from this answer:
Function.create(db.getConnection(), "getNickName", new Function() {
protected void xFunc() throws SQLException {
String name = value_text(0);
String nickName = ...; // implement myparsingfunction here
result(nickName);
}
});
and use it like this: UPDATE PERSONS SET NICKNAME = getNickName(NAME);
SQLite does not support stored procedures so that option is out of the table.
I'm not sure which of these options would provide the best performance (certainly using pure SQL would be faster but that may not be a viable solution). You should benchmark each solution to find the one that fits you.

Why do I see NotUpdatable when I invoke ResultSet.refreshRow()?

When I invoke following rows:
Statement statement = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
ResultSet resultSet = statement.executeQuery("select * from user");
resultSet.next();
resultSet.refreshRow();//exception throws here
I see following exception:
com.mysql.jdbc.NotUpdatable: Result Set not updatable.This result set
must come from a statement that was created with a result set type of
ResultSet.CONCUR_UPDATABLE, the query must select only one table, can
not use functions and must select all primary keys from that table.
See the JDBC 2.1 API Specification, section 5.6 for more details.This
result set must come from a statement that was created with a result
set type of ResultSet.CONCUR_UPDATABLE, the query must select only one
table, can not use functions and must select all primary keys from
that table. See the JDBC 2.1 API Specification, section 5.6 for more
details.
I wondered this exception because if read refreshRow method javadoc we can find following:
The refreshRow method provides a way for an application to explicitly
tell the JDBC driver to refetch a row(s) from the database
Thus following direction: database --> ResultSet
I have following understanding:
updatable is possibility to use following direction:
ResultSet --> database
Thus I don't understand cause of problem.
please clarify.
When you are using, ResultSet.CONCUR_READ_ONLY, you are getting an exception, that
com.mysql.jdbc.NotUpdatable: Result Set not updatable.This result set
must come from a statement that was created with a result set type of
ResultSet.CONCUR_UPDATABLE, the query must select only one table, can
not use functions and must select all primary keys from that table.
See the JDBC 2.1 API Specification, section 5.6 for more details.\
So, changing ResultSet.CONCUR_READ_ONLY to ResultSet.CONCUR_UPDATABLE, solved your problem. Correct?
Now, as I understand, you don't want to do that. Am I right? If yes, then I think you are confusing ResultSet with Database,
ResultSet.CONCUR_READ_ONLY, means read only ResultSet, not Database, similarly
ResultSet.CONCUR_UPDATABLE, means updatable ResultSet, not Database.
The method, resultSet.refreshRow(), suppose to update the resultSet, hence it rightly requires updatable ResultSet. I hope it's clear now.

Get dynamic SQL column names from Hibernate

I have an Oracle table that has a CLOB in it. Inside this CLOB can be a SQL statement. This can be changed at any time.
I am currently trying to dynamically run these SQL statements and return the column names and data back. This is to be used to dynamically create a table on the web page.
Using Hibernate, I create the query and get the data like so:
List<Object[]> queryResults = null;
SQLQuery q = session.createSQLQuery(sqlText);
queryResults = q.list();
This gets the data I need, but not the column names. I have tried using the getReturnAliases() method, but it throws an error that the "java.lang.UnsupportedOperationException: SQL queries do not currently support returning aliases"
So my question is: Is there a way through Hibernate to get these values dynamically?
You can use :
q.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List<Map<String,Object>> aliasToValueMapList=query.list();
to get column names in createSQLQuery.
For more details please refer to this question.
You can use the addScalar method to define the columns.
Look at 16.1.1
https://docs.jboss.org/hibernate/orm/3.3/reference/en-US/html/querysql.html
You could implement a ResultTransformer ( http://docs.jboss.org/hibernate/orm/4.3/javadocs/org/hibernate/transform/ResultTransformer.html ) and set it on the native query. I think with a native SQL query you get the aliases as specified in the SQL as alias parameter in the callback method.
In 2018 I would suggest using NativeQueryTupleTransformer with native queries.
query.setResultTransformer(new NativeQueryTupleTransformer());
The result format is List<Tuple>. This format is very convenient to work with native SQL queries.

Executing multi - statement query in one session

I have asked this question and wanted to edit it , however StackOverflow for some reason did not allow me to edit . So here is the edited version
For example a query :
create volatile table testTable as (select * from ... blah blah) ;
select top 10 * from testTable ;
drop table testTable ;
It executes perfect in sql assistance as one session. I am sure it is possible to execute it in Java in one session.
Goal : need to execute it in one session similar to sql assistant so that it is possible to refer to the volatile table in the subsequent select statement. Also the data from the select statement should be saved in the ResultSet
PS
I saw one answer to a similar question about mysql. The trick is to turn on allow multiple queries
String dbUrl = "jdbc:mysql:///test?allowMultiQueries=true";
For teradata specifically,
what is the solution ?
I tried
String dbUrl = "jdbc:odbc:dsn?allowMultiQueries=true";
What is exactly failing?
Is there an error message "testtable doesn't exist"? Then your program closes the connection after each request.
Is the table empty when you do the SELECT? Then you forgot to add ON COMMIT PRESERVE ROWS to the CREATE.

How to search and insert a value using java code?

String link = "http://hosted.ap.org";
I want to find whether the given url is already existing in the SQL DB under the table name "urls". If the given url is not found in that table i need to insert it in to that table.
As I am a beginner in Java, I cannot really reach the exact code.
Please advise on this regard on how to search the url in the table.
I am done with the SQL Connection using the java code. Please advise me on the searching and inserting part alone as explained above.
PreparedStatement insert = connectin.preparedStateme("insert into urls(url) vlaues(?)");
PreparedStatement search = connectin.preparedStateme("select * from urls where url = ?");
search.setString(1, <your url value to search>);
ResultSet rs = search.executeQuery();
if (!rs.hasNext()) {
insert.setString(1, <your url value to insert>);
insert.executeUpdate();
}
//finally close your statements and connection
...
i assumed that you only have one field your table and field name is url. if you have more fields you need to add them in insert query.
You need to distinguish between two completely separate things: SQL (Structured Query Language) is the language which you use to communicate with the DB. JDBC (Java DataBase Connectivity) is a Java API which enables you to execute SQL language using Java code.
To get data from DB, you usually use the SQL SELECT statement. To insert data in a DB, you usually use the SQL INSERT INTO statement
To prepare a SQL statement in Java, you usually use Connection#prepareStatement(). To execute a SQL SELECT statement in Java, you should use PreparedStatement#executeQuery(). It returns a ResultSet with the query results. To execute a SQL INSERT statement in Java, you should use PreparedStatement#executeUpdate().
See also:
SQL tutorial
JDBC tutorial

Categories