ResultSet not open. Operation 'getString' not permitted. Verify that autocommit is off.? - java

I am using apache derby and getting the above error here is my code, actually I'm just not getting all the children under the parents, it only give me one level of children, so kindly tell me how to make tree parent and child but this gives only one level of child with above error
getting connection
public static Connection getConnection(){
Connection connection = null;
try {
Class.forName("org.apache.derby.jdbc.ClientDriver").newInstance();//
//Get a connection
connection = DriverManager.getConnection(dbURL);
connection.setAutoCommit(false);
connection.getAutoCommit();
} catch (Exception except) {
System.out.println(except);
}
return connection;
}
and error in second loop at last reading rs1
Statement stmt;
stmt = MainUI.getConnection().createStatement();

Nesting the result sets is your problem, I believe.
To have two different result sets open, you must have two separate Statement instances, so each can have its own ResultSet. Otherwise, running the second query on the same Statement instance will close the first ResultSet.
See this answer for more information: https://stackoverflow.com/a/8579669/193453
Also, have a look at the Javadocs for the java.sql.Statement class:
By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of one ResultSet
object is interleaved with the reading of another, each must have been
generated by different Statement objects. All execution methods in the
Statement interface implicitly close a statment's current ResultSet
object if an open one exists.

Related

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.

Execute multiple queries using a single JDBC Statement object

In JDBC, can I use single Statement object to call executeQuery("") multiple times? Is it safe? Or should I close the statement object after each query, and create new object for executing another query.
E.G:
Connection con;
Statement s;
ResultSet rs;
ResultSet rs2;
try
{
con = getConnection();
// Initially I was creating the Statement object in an
// incorrect way. It was just intended to be a pseudocode.
// But too many answerers misinterpretted it wrongly. Sorry
// for that. I corrected the question now. Following is the
// wrong way, commented out now.
// s = con.prepareStatement();
// Following is the way which is correct and fits for my question.
s = con.createStatement();
try
{
rs = s.executeQuery(".......................");
// process the result set rs
}
finally
{
close(rs);
}
// I know what to do to rs here
// But I am asking, should I close the Statement s here? Or can I use it again for the next query?
try
{
rs2 = s.executeQuery(".......................");
// process the result set rs2
}
finally
{
close(rs2);
}
}
finally
{
close(s);
close(con);
}
Yes you can re-use a Statement(specifically a PreparedStatement) and should do so in general with JDBC. It would be inefficient & bad style if you didn't re-use your statement and immediately created another identical Statement object. As far as closing it, it would be appropriate to close it in a finally block, just as you are in this snippet.
For an example of what you're asking check out this link: jOOq Docs
I am not sure why you are asking. The API design and documentation show it is perfectly fine (and even intended) to reuse a Statement object for multiple execute, executeUpdate and executeQuery calls. If it wouldn't be allowed that would be explicitly documented in the Java doc (and likely the API would be different).
Furthermore the apidoc of Statement says:
All execution methods in the Statement interface implicitly close a statment's [sic] current ResultSet object if an open one exists.
This is an indication that you can use it multiple times.
TL;DR: Yes, you can call execute on single Statement object multiple times, as long as you realize that any previously opened ResultSet will be closed.
Your example incorrectly uses PreparedStatement, and you cannot (or: should not) be able to call any of the execute... methods accepting a String on a PreparedStatement:
SQLException - if [...] the method is called on a PreparedStatement or CallableStatement
But to answer for PreparedStatement as well: the whole purpose of a PreparedStatement is to precompile a statement with parameter placeholders and reuse it for multiple executions with different parameter values.
I can't find anything in the API docs that would state, that you shouldn't call executeQuery() on a given PreparedStatement instance more than once.
However your code does not close the PreparedStatement - a call to executeQuery() would throw a SQLException in that case - but the ResultSet that is returned by executeQuery(). A ResultSet is automatically closed, when you reexecute a PreparedStatement. Depending on your circumstances you should close it, when you don't need it anymore. I would close it, because i think it's bad style not to do so.
UPDATE Upps, I missed your comment between the two try blocks. If you close your PreparedStatement at this point, you shouldn't be able to call executeQuery() again without getting a SQLException.
A Prepared Statement tells the database to remember your query and to be prepared to accept parameterized variables to execute in that query. It's a lot like a stored procedure.
Prepared Statement accomplishes two main things:
It automatically escapes your query variables to help guard against SQL Injection.
It tells the database to remember the query and be ready to take variables.
Number 2 is important because it means the database only has to interpret your query once, and then it has the procedure ready to go. So it improves performance.
You should not close a prepared statement and/or the database connection in between execute calls. Doing so is incredibly in-efficient and it will cause more overhead than using a plain old Statement since you instruct the database each time to create a procedure and remember it. Even if the database is configured for "hot spots" and remembers your query anyways even if you close the PreparedStatement, you still incur network overhead as well as small processing time.
In short, keep the Connection and PreparedStatement open until you are done with them.
Edit: To comment on not returning a ResultSet from the execution, this is fine. executeQuery will return the ResultSet for whatever query just executed.
Firstly I am confused about your code
s = con.prepareStatement();
Is it work well?I can't find such function in JAVA API,at least one parameter is needed.Maybe you want to invoke this function
s = con.createStatement();
I just ran my code to access DB2 for twice with one single Statement instance without close it between two operation.It's work well.I think you can try it yourself too.
String sql = "";
String sql2 = "";
String driver = "com.ibm.db2.jcc.DB2Driver";
String url = "jdbc:db2://ip:port/DBNAME";
String user = "user";
String password = "password";
Class.forName(driver).newInstance();
Connection conn = DriverManager.getConnection(url, user, password);
Statement statement = conn.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
int count = 0;
while (resultSet.next()) {
count++;
}
System.out.println("Result row count of query number one is: " + count);
count = 0;
resultSet = statement.executeQuery(sql2);
while (resultSet.next()) {
count++;
}
System.out.println("Result row count of query number two is: " + count);

Java ResultSet working with postgresql

I have a table on my database where it holds 2 columns: uid1 - someone's id, uid2 - his friend.
I want to create a list where I someone's friend - till 5 depth connection.
So I built the following recursive method:
private void recursive(int theUid,ResultSet rs,ArrayList<Integer> friends,int count,int next,PreparedStatement pstmt) throws SQLException{
if(count>=1 && next==theUid){
return;
}
else if(count>=DEPTH_OF_CONNECTION){
return;
}
else{
pstmt.setInt(1,next);
rs=pstmt.executeQuery();
count++;
while(rs.next()) {
friends.add(rs.getInt(1));
recursive(theUid,rs,friends,count,rs.getInt(1),pstmt);
}
}
}
}
And I got the following error:
Exception in thread "main" org.postgresql.util.PSQLException: This
ResultSet is closed. at
org.postgresql.jdbc2.AbstractJdbc2ResultSet.checkClosed(AbstractJdbc2ResultSet.java:2654) at
org.postgresql.jdbc2.AbstractJdbc2ResultSet.next(AbstractJdbc2ResultSet.java:1786)
Can you help me find what is the problem?
Javadoc for jdbc Statement says
By default, only one ResultSet object per Statement object can be open at the same time.
So my guess is you are trying to open too many resultsets for the same PreparedStatement at the same time.
edit:
Postgres jdbc driver doc seems to confirm it:
You can use a single Statement instance as many times as you want. You could create one as soon as you open the connection and use it for the connection's lifetime. But you have to remember that only one ResultSet can exist per Statement or PreparedStatement at a given time.
From what I can tell, you are using the ResultSet object to store your statement results and then passing it as a parameter to the recursive function call. So basically you are overwriting the variable and losing the reference to it. You should either write your sql statement to retrieve the data you need or not pass the same ResultSet object to the recursive call.

Closing a database connection in Java

I have the following method in my database class that returns a resultset for a given SQL statement:
public static ResultSet sqlStatement(String query) throws SQLException{
ResultSet result = null;
Connection conn = connect();
Statement newStatement = conn.createStatement();
result = newStatement.executeQuery(query);
conn.close();
return result;
}
I want to close the connection to the database before i return the resultset but it throws the following exception:
java.sql.SQLException: out of memory
I'm a java noob and experimenting so any help is much appreciated.
In my past experience(No document or anything), I would understand the "ResultSet" like a pointer in C. I bet it would cache some rows from database when you execute your query..
Therefore, if you close connection and then try to use resultset, all those cached resultset does not have proper information and getting next cache etc. As a result, it would throw out of memory exception..
Anyway proper way to use those in java..
Connection con...
try{
create connection
execute query
use your resultset completely..
}catch(...){
}finally{
close connection;
}
Hope it would help
Put the conn.close() in a finally block so that it gets executed event if an exception is thrown.
always, always, always close your database resources in a finally block!
i doubt your logic will work as is. a ResultSet is only usable while the connection is open. you need to process the entire ResultSet before you close the connection.
Apart from closing resources in a finally block, you also have to close your PreparedStatement and your ResultSet. In fact, you shouldn't return the ResultSet and keep it open for too long. Instead, you could read it into some sort of intermediary data store, such as a List<Object[]>.
On the other hand, you're not getting a java.lang.OutOfMemoryError, so possibly it's your database itself that ran out of memory

Is there any way to prepare a sql statement in Java without using a Connection object?

I'm pretty new to JDBC, so this is probably a very straightforward question.
I have to run several SQL statements, so I'm trying to write a generic "runSQLResultSet" method that takes a String sql statement and returns a ResultSet. I want it to take care of opening the database connection, executing the statement, storing the ResultSet in a CachedRowSetImpl object (so that it will persist after the connection is closed), and closing the connection. I created a method that does this and it works.
My problem now is that I want to be able to use it for dynamic statements that are built with variables. I looked around, and it seems that I should really change my method to take a PreparedStatement instead of just a plain String. Then I can build the PreparedStatement on the other side and pass it to the method. The problem is that I can't seem to create a PreparedStatement without a Connection object. I can open the connection before preparing the statement, but that defeats my purpose of factoring out the database processing into the runSQLResultSet method. I need a way to build a SQL statement with dynamic components, without a connection object, and pass it to a method that will then execute it. Is there any way to do this with a PreparedStatement? Is there any other statement object I can use instead? Otherwise - is there any better way to do this?
public ResultSet excuteStatement(String statement, Object... params){
statement = conn.prepareStatement(statement);
int i = 1;
for (Object o:params){
statement.setObject(i++,o);
}
ResultSet rs = statement.executeQuery();
return rs;
}
You cannot create one without a DB connection. A PreparedStatement will be precompiled in the DB and thus really needs an open connection.
You can instead also just consider to dynamically build the SQL string instead. Generating the PreparedStatement placeholders (the ? things) in a loop and and using String#format() to put them in the SQL string. u can also consider to just pass the variables to your runSQLResultSet method and build there instead.
As per the comments, here's an example:
try {
connection = database.getConnection();
statement = connection.prepareStatement(SQL);
setValues(statement, values);
// ...
.
public static void setValues(PreparedStatement preparedStatement, Object... values) throws SQLException {
for (int i = 0; i < values.length; i++) {
preparedStatement.setObject(i + 1, values[i]);
}
}
If I understand you correctly, you want to use the same query with different variables inserted into the query. You can have your method return the ResultSet like it currently does and pass the variables in as parameters to the method.
then you can put the parameters into the query inside of the method.
public ResultSet getResult(String param1, String param2){
statement = conn.prepareStatement(yourQuery);// conn must be an open connection
statement.setString(1,param1);
statement.setString(2,param2);
ResultSet rs = statement.execusteQuery();
return rs;
}
That's a basic example of how you might do something like that if I understood your question correctly.
what you are missing is the concept of Database connection pooling, you should never be instantiaing connections directly, the pool controls the database connections under the covers. You can look at my open source project SQL Construction Kit for some inspiration on one light weight way to deal with JDBC and how to build dynamic SQL statements using Factory and Builder patterns.

Categories

Resources