This question already has answers here:
ResultSet exception - before start of result set
(6 answers)
Closed 5 years ago.
I try to get some data form database. The connection method works for sure, but I have a problem getting any data form DB:
SQLConnect s = new SQLConnect();
Connection c = s.getConnection();
Statement st = c.createStatement();
ResultSet rs = st.executeQuery("select * from produkty");
System.out.println(rs.getString(2));
The problem is with the last line (when I comment it, no error appears).
Error message:
Connected to database
Exception in thread "main" java.sql.SQLException: Before start of result set
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
at com.mysql.jdbc.ResultSetImpl.checkRowPos(ResultSetImpl.java:841)
at com.mysql.jdbc.ResultSetImpl.getStringInternal(ResultSetImpl.java:5656)
at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5576)
at antmedic.Main.main(Main.java:85)
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)
Thanks for any help
You need to call ResultSet#next() to shift the resultset cursor to the next row. Usually, when there's means of multiple rows, do this in a while loop.
while (rs.next()) {
System.out.println(rs.getString(2));
}
Or when you expect zero or one row, use an if statement.
if (rs.next()) {
System.out.println(rs.getString(2));
}
See also:
JDBC tutorial
Examples of how to traverse the ResultSet correctly
As you get the ResultSet object, the cursor points to the row before the first row, So after calling
while (rs.next()) {
//your code
}
the cursor points to the next row
i.e. the first row.
Remember, whenever select query fires for retrieving the data from database into ResultSet,
so the structure of ResultSet is
-> Zero Record Area
-> Database Record Area
-> No Record Area
that's why alwayz we must put next() with ResultSet object so it can move from Zero Record Area to Database Record Area.
while(rs.next())
{
System.out.println(rs.getString(1));
System.out.println(rs.getString(2));
}
at the place of 1, 2, .... we can use the database columns name also. But technically always we use indexing like 1,2,3,.... its reason for any updation happening in future at our database like changes the column name so it can't be occur any problem for us because we haven't used the columns names.
Related
This question already has an answer here:
Why do I get java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. java derby database?
(1 answer)
Closed 6 years ago.
In connection with another programming project, I am prototyping a JDBC project (with Netbeans, Java, and a Derby database). My program needs to iteratively update all the rows in a database table as follows:
There are three columns in the table: famousName, famousQuote, hashKey.
Originally, the famousQuote column contains a verbatim quote. I want to go down that column using a while loop, get the checksum of the ascii letters, bitwise "AND" with the hashKey value, and then replace the verbatim quote with an "encrypted" value.
As of right now, I try to extract the verbatim famousQuote using a ResultSet object, perform necessary encryption, and then an SQL statement that updates the value. All of this takes place in a while(rs.next()) loop as follows:
(pseudo-code): //all necessary database connections and variable declared here.
String sqlStatement = "Select * FROM mainTable ORDER BY famousName";
ResultSet rs = stmt.executeQuery(sqlStatement);
while(rs.next()){
tempString1 = rs.getString("famousQuote");
tempString2 = rs.getString("hashKey");
tempString3 = EncryptionAlgorithm.EncryptStatement(tempString1, tempString2);
sqlStatement = "UPDATE maintable SET famousQuote=tempString3 WHERE hashKey=tempString2";
(note, there is a bit of pseudo-code regarding the WHERE part,
but I'm sure it's immaterial to the error message I'm getting.)
stmt.executeUpdate(sqlStatement);
}
This seemed like a good idea until the program started throwing errors such as:
ResultSet not open. Operation 'next' not permitted. Verify that autoCommit is off
I later read in the documentation (concerning ResultSet):
A ResultSet object is automatically closed when the Statement object that generated it
is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.
Lastly, I guess I could try moving the ResultSet rs declaration inside the while loop, so that it would instantiate a new ResultSet object, but I'm pretty sure this would lose my place in the database (re-updating the first row perpetually).
I'm now at a standstill on how to iterate my way down the table rows, executing my EncryptionAlgorithm on each quote, and then updating the column values in place.
I apologize in advance if my JDBC is a little rusty, but something like this might do the trick:
// 'conn' is your JDBC connection
Statement stmt = conn.createStatement();
PreparedStatement update = conn.prepareStatement(
"UPDATE maintable SET famousQuote=tempString3 WHERE hashKey=tempString2";
String sqlStatement = "Select * FROM mainTable ORDER BY famousName";
ResultSet rs = stmt.executeQuery(sqlStatement);
while(rs.next()){
tempString1 = rs.getString("famousQuote");
tempString2 = rs.getString("hashKey");
tempString3 = EncryptionAlgorithm.EncryptStatement(tempString1, tempString2);
update.setObject(1, tempString3);
update.setObject(2, tempString2);
update.executeUpdate(sqlStatement);
}
I need to run several queries in a row
Statement st = cnx.createStatement();
ResultSet rs = st.executeQuery( "SELECT [good stuff]");
// do something smart with rs
rs = st.execute( "SELECT [better stuff]");
// do something smarter with rs
rs = st.execute( "SELECT [best stuff]");
// you got it
try{ rs.close();} catch( SQLException ignore){};
try{ st.close();} catch( SQLException ignore){};
Is this a problem that the first two ResultSet are not properly closed or is it implicitely done during garbage collection?
As soon as you execute the 2nd query, the previous ResultSet is automatically closed. And as far as Garbage Collection is concerned, you don't have to worry about that. You can just have a stmt.close() at the end that's all. It will automatically close all the related ResultSet objects.
Take a look at : - ResultSet#close documentation, which says that: -
A ResultSet object is automatically closed by the Statement object
that generated it when that Statement object is closed, re-executed,
or is used to retrieve the next result from a sequence of multiple
results.
If you want to test, whether your resultset gets closed or not, you can use a while loop to iterate over the result set and inside the while loop, create another query and assign it to same result set. You will see that an Exception will be thrown..
ResultSet res = stmt.executeQuery("SELECT * FROM sometable");
while (res.next()) {
res.getString(1);
// Closes the previous `ResultSet`
res = stmt.executeQuery("SELECT * FROM othertable");
}
So, in the above code, on the 2nd iteration, you will get an Exception: - Cannot perform operation after ResultSet is closed
I don't know what's your problem, but if you have some problems to run this code, you can try to close connection and open other to make the second query. Some database products, like SQLite, only admit one open connection. If you have any problem with database access, you should try that.
I'm using java to do batch inserts into a mysql table:
cnx = lconnect.openConnection();
mStatement = cnx.createStatement();
boolean firstTime = true;
PreparedStatement preparedStatement = null;
preparedStatement = cnx.prepareStatement(strQuery);
preparedStatement.setString(param1);
preparedStatement.setString(param2);
....
preparedStatement.addBatch();
preparedStatement.setString(param1);
preparedStatement.setString(param2);
preparedStatement.addBatch();
preparedStatement.setString(param1);
preparedStatement.setString(param2);
preparedStatement.execute();
Is there any way to really know the number of inserted lines ?
I think my piece of code it's working (?) by the number of lines in the DB does not match with the number of lines supposed to be inserted, so I'm thinking I have a problem with y inserts maybe.
You have to call executeBatch(). The returned array contains the information you want.
From the JavaDoc:
Returns:
an array of update counts containing one element for each command in the batch. The elements of the array are ordered according to the
order in which commands were added to the batch.
Use PreparedStatement object for each batch record :)
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.
I am trying to use some query result to generate another query and execute the new query but that does not seem to work. The second query is not being executed. Can someone please tell me why? This is that part of the code.
Statment stmt = connnection.createStatement();
Statment stmt2 = connnection.createStatement();
ResultSet r = stmt.executeQuery("Select * from employees");
while (r.next()) {
String Str = "Select name from employees where employeeId = " + (r.getInt(3) + 1);
System.out.println(str);
query = stmt2.executeQuery(str);
System.out.println(query.getString(1));}
The right query seems to be generated, but just won't execute. Is there a reason why this is so. BTW "query" is declared as resultset.
Thanks
you can only have one statement executing at one moment in time against one database connection -- so you can either open another database connection and execute the second statement in the 2nd connection, or iterate through the resultset from first statement and store the employees database id's (e.g. in an array/collection) then close that statement and run the second one, this time retrieving the id's from the array/collection you saved them in.