Creating a Scroll_Insensitive ResultSet using the SAP Hana JDBC Driver - java

I'm trying to create a Scroll_Insensitive ResultSet using/in the SAP Hana JDBC Driver. When I run the below code:
Class.forName("com.sap.db.jdbc.Driver");
connection = DriverManager.getConnection("jdbc:sap://10.32.86.10:30115/autocommit=false",username,password);
java.sql.Statement stmt = connection.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
java.sql.ResultSet resultSet = stmt.executeQuery("SELECT * FROM SAMPLE");
resultSet.next();
String hello = resultSet.getString(1);
I get the following exception:
com.sap.db.jdbc.exceptions.jdbc40.SQLDataException: Invalid argument resultSetType, use TYPE_FORWARD_ONLY.
If I replace the third line with:
java.sql.Statement stmt = connection.createStatement();
It works without a hitch. I need the ResultSet to be Scroll_Insensitive to be able to use methods such as
rs.previous(), rs.last(), rs.getRow(), etc.
The same code works perfectly for MySQL, Microsoft SQL, TeraData & Oracle. What might the problem with SAP Hana? Is there a workaround?

The answer simply is what the error message implies: SAP HANA's JDBC driver (currently) only provides you with a FORWARD ONLY cursor type.
Question here would be what specific characteristic of the TYPE_SCROLL_INSENSITIVE cursor type do you actually need here?

I also faced the same error where I wanted to check if the processed row was the last row of the result set and tried rs.last() method on resultset object. Here is what I found on SAP SCN:
Due to performance improvement when using forward only cursor we
changed the default for the resultset type from TYPE_SCROLL_SENSITIVE
to TYPE_FORWARD_ONLY starting with JDBC driver version 7.6. So I guess
the exception comes from a statement where you didn't set the
result set type while creating it. Please check if all of the
statements that you want to be scrollable have set the correct
resultset type.
here is the link to the thread:
The operation is not allowed for result set type FORWARD_ONLY

Related

Creating Table in AWS Redshift with AWS Java SDK

I am trying to create a temporary table inside of AWS redshift using the java SDK.
// Redshift JDBC 4.1 driver: com.amazon.redshift.jdbc41.Driver
String command = "CREATE TABLE test (FirstName varchar(255));"
Class.forName("com.amazon.redshift.jdbc41.Driver");
conn = DriverManager.getConnection(dbURL, props);
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(command);
When running this code the table is created successfully but on the return, an error is thrown
com.amazon.dsi.dataengine.impl.DSISimpleRowCountResult cannot be cast to com.amazon.dsi.dataengine.interfaces.IResultSet
Everything will work if I use a command that returns something, such as
"Select * FROM test;"
"SELECT * FROM test LIMIT 0;"
I didn't see any documentation for this problem in the AWS READMEs or other stack overflow questions for this problem. It seems to me that there is a special class in the driver for when nothing is returned from the statement that is not able to be cast to the ResultSet class.
The redshift driver version is 1.1.13.1013 .
Any help would be greatly appreciated!
I had the same problem. You can solve this easily. Instead of
stmt.executeQuery(command);
please try
stmt.execute(command);

Java HSQLDB connection issue

I have been making a program that is using HSQL to connect to a database that I created. For some reason some methods in my class can call on the database and perform commands, while other parts cannot. I keep getting this error,
java.sql.SQLFeatureNotSupportedException: feature not supported
and here is the method,
public List<CustomerInfo> DBgetInfo(String Customer)
throws ClassNotFoundException, SQLException {
Class.forName("org.hsqldb.jdbcDriver");
Connection con = DriverManager.getConnection(urlConnection, userId,
password);
Statement stmt= con.createStatement();
String query = "SELECT * FROM PUBLIC.CUSTOMER";
ResultSet rs = stmt.executeQuery(query);
rs.first(); //The error happens on this line
rs.close();
stmt.close();
con.close();
}
I have ran the debugger multiple times and there error is in this method on the rs.first line. I have tried remaking the DB, reimporting all the files, checking to make sure the command is correct, and ect... The weird thing is that earlier in this class I have a method very similar to this, but it has no issues. I really can't figure out what the problem is.
According to the documentation this error occurs:
Throws:
SQLException - if a database access error occurs, this method is called on a closed result set or the result set type is TYPE_FORWARD_ONLY
SQLFeatureNotSupportedException - if the JDBC driver does not support this method
Earlier on the same page, there is a section on HSQL specific details for result sets. To call first you need to modify your statement creation:
ResultSet object generated by HSQLDB is by default of ResultSet.TYPE_FORWARD_ONLY (as is standard JDBC behavior) and does not allow the use of absolute and relative positioning methods. If a statement is created with:
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
then the ResultSet objects it produces support using all of the absolute and relative positioning methods of JDBC2 to set the position of the current row...
But you might want to think about why you need to call first.

Java jdbc warning when using TYPE_SCROLL_ SENSITIVE

This is quoted from OCA/OCP Java® SE 7 Programmer I & II Study Guide (Exams 1Z0-803 & 1Z0-804) book :
For example, suppose that we mistakenly set the result set type to
TYPE_SCROLL_ SENSITIVE when creating a Statement object. This does not
create an exception; instead, the database will handle the situation
by chaining a SQLWarning to the Connection object and resetting the
type to TYPE_FORWARD_ONLY (the default) and continue on.
I don't know why setting the statement of type TYPE_SCROLL_ SENSITIVE will cause resetting the type to TYPE_FORWARD_ONLY, am I missing anything?
As per above this code will setting the type back to TYPE_FORWARD_ONLY
Connection conn =
DriverManager.getConnection("jdbc:derby://localhost:1527/BookSellerDB",
"bookguy", "$3lleR");
Statement stmt =
conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String query = "SELECT * from Book WHERE Book.Format = 'Hardcover'";
ResultSet rs = stmt.executeQuery(query);
See here: https://docs.oracle.com/cd/A87860_01/doc/java.817/a83724/resltse2.htm#1018253
To produce a scroll-sensitive result set:
A query cannot use "SELECT *". (But see the workaround below.)
A query can select from only a single table.
A query cannot use ORDER BY.
It continues:
If the specified result set type or concurrency type is not feasible, the Oracle JDBC driver uses the following rules in choosing alternate types:
If the specified result set type is TYPE_SCROLL_SENSITIVE, but the JDBC driver cannot fulfill that request, then the driver attempts a downgrade to TYPE_SCROLL_INSENSITIVE.
If the specified (or downgraded) result set type is TYPE_SCROLL_INSENSITIVE, but the JDBC driver cannot fulfill that request, then the driver attempts a downgrade to TYPE_FORWARD_ONLY.
Ok, those are Oracle Database specific, but it shows an example of downgrading.

ResultSet update row is not working

I want to update raw in my ResultSet while I looping through the result set. Following is my code
try {
String query="SELECT * FROM smsmessage WHERE recipient = ? and sent_status = 'pending' LIMIT ? ";
PreparedStatement prepStmt = conn.prepareStatement(query);
prepStmt.setString(1,shortCode);
prepStmt.setInt(2, Integer.parseInt(batchSize));
ResultSet rs=prepStmt.executeQuery();
while (rs.next()) {
//update the selected message sent status to "sent" from "pending"
rs.updateString("sent_status","sent");
rs.updateRow();
}
} catch (SQLException e) {
log.error("MySQL exception",e);
}
What should be the possible reason for this?
I am getting following error
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.
As the stacktrace tells, you have to create a statement that allows its resultset to be updateable:
PreparedStatement prepStmt= conn.prepareStatement(query,
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
From the API of ResultSet (http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html):
A default ResultSet object is not updatable and has a cursor that moves forward only. Thus, you can iterate through it only once and only from the first row to the last row. It is possible to produce ResultSet objects that are scrollable and/or updatable. The following code fragment, in which con is a valid Connection object, illustrates how to make a result set that is scrollable and insensitive to updates by others, and that is updatable. See ResultSet fields for other options.
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable
Well, you should start by carefully reading the error text:
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 means that the result set is not updateable. You can't update a result set that is not updateable.
It also says that this result set must come from a statement that was created with a result set type of ResultSet.CONCUR_UPDATABLE. This means that your statement - in this case a PreparedStatement, must be created with that option.
Finally, it directs you to the documentation. JDBC 2.1 is a bit outdated, and you can find all the relevant data in the usual J2SE Documentation. Let's start from the documentation for ResultSet. It says:
A default ResultSet object is not updatable and has a cursor that
moves forward only. Thus, you can iterate through it only once and
only from the first row to the last row. It is possible to produce
ResultSet objects that are scrollable and/or updatable. The following
code fragment, in which con is a valid Connection object, illustrates
how to make a result set that is scrollable and insensitive to updates
by others, and that is updatable. See ResultSet fields for other
options.
And the code fragment it shows is:
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable
So you see, they are using a statement where you add two parameters, that enable you to scroll through the data and update it. But they are using a Statement rather than a PreparedStatement. Is this applicabe to PreparedStatement as well?
Going to the PreparedStatement documentation will not help you much, but wait, you are using the connection object to prepare the statement, perhaps it will help you?
Yes, indeed, there is a method in Connection that allows you to pass the parameters, just like the Statement in the example.
PreparedStatement prepareStatement(String sql,
int resultSetType,
int resultSetConcurrency)
throws SQLException
So now you must ask yourself, what kind of resultSetType do I need, and what kind of resultSetConcurrency?
Scrolling your statement is not necessary for your current question, so you can use the default. If you look at the documentation of the plain preparedStatement(String) you'll see:
Result sets created using the returned PreparedStatement object will
by default be type TYPE_FORWARD_ONLY and have a concurrency level of
CONCUR_READ_ONLY. The holdability of the created result sets can be
determined by calling getHoldability().
...which is why your initial prepared statement was not updatable, by the way. But anyway, it tells you that the default for the scrolling type is TYPE_FORWARD_ONLY.
What about the updating, which is the important part? Well, the options are CONCUR_READ_ONLY and CONCUR_UPDATABLE. So you need to use the second one. That's what the error message told you, after all.
Conclusion:
You need to use
PreparedStatement prepStmt = conn.prepareStatement(
query,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
This will give you an updatable result set.
And this is how to find your answer from the error message that you get.

java.sql.SQLRecoverableException: No more data to read from socket

I have a database table in oracle which has a column of type DATE. It looks like the table below
TABLE1
ID PRODUCT_NAME ITEM_CNT ENTERED_DATE
1 prod1 500 2012-07-01
2 prod2 1000 2012-06-30
in my java code, I want to get the total item_cnt for a certain date range. here is the code sample
String sql = "select sum(item_cnt) from table1 where entered_date between ? and ?";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rset = null;
try{
conn = getConnection(url, user, passwd);
pstmt = conn.prepareStatement(sql);
pstmt.setDate(1, java.sql.Date.valueOf(from_date)); //from_date is a string of "yyyy-mm-dd"
pstmt.setDate(2, java.sql.Date.valueOf(to_date)); //to_date is a string of "yyyy-mm-dd"
rset = pstmt.executeQuery();
....
}catch(SQLException e){
//do something
} finally{
//clean up
}
This code was running fine for a while until three days ago, I start getting the following exception at line pstmt.executeQuery();
java.sql.SQLRecoverableException: No more data to read from socket
at oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1157)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:290)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:884)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1167)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1289)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3628)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1493)
I tried to search for answers but couldn't find anything that really explains it. then I changed my sql query to
"select sum(item_cnt) from table1 where entered_date between to_date(?, 'yyyy-mm-dd') and to_date(?, 'yyyy-mm-dd')";
and instead of setting date, I changed the prepared statement to the following
pstmt.setString(1, from_date);
pstmt.setString(2, to_date);
Then the exception is gone.
Another confusion is, when I populate my table, I am still using the following
pstmt.setDate(1, java.sql.Date.valueOf(date)); //date is a string of format "yyyy-mm-dd"
and it is still working. only the select statement was giving me exceptions.
Now everything is working but I really want to know why. Anyone knows?
I did upgrade my java to 1.7.0_03-b05 recently. and I am using ojdbc6.jar. The oracle is 11g. Could this be the driver's problem? is ojdbc7 out?
I was facing this exception while working over JDBC with IBM WAS 7.0, I had performed a JCA lifecycle management operation on data source. Which is like controlling the runtime status of the data source. Purge removes the contents of connection pool for the data source. However, in WAS this purging the pool will not affect the ongoing transactions. Check on your side.
Another thing which I performed was; the disk space was full on directory where Oracle was installed, I added extra space over that.
As a best practice, I stay away from java.sql.Date class and use to_date() and to_char() functions while dealing with Dates in Java with Oracle.

Categories

Resources