I execute:
select * from table_name order by column desc;
And I want to go through the items sequentially. I got the ResultSet from that and did:
while(set.next()) {
// processing code
}
Unfortunately, that skips the very first element. What's the best way to iterate through the entire ResultSet and include the very first element?
Use:
set.beforeFirst();
while(set.next()) {
// Your code
}
This will run the body of your loop once before advancing the ResultSet. You don't want to use a do loop (my previous answer) because it will throw an Exception if the query has 0 rows returned.
I know this is really old but my search hit here and after the solution didn't work for me (forward only result set) I believe the issue was never really addressed. In my case, I was doing:
jdbcTemplate.query(sql, rs -> {
while(rs.next()) {
// processRow
}
// no return statement
, args);
I then looked more closely at the method that was being called and the second argument was a "RowCallbackHandler" and not a "ResultSetExtractor" so the correct use of this code is:
jdbcTemplate.query(sql, rs -> {
// processRow
}, args);
This does the "while (rs.next())" loop for you.
I'd wager the OP was doing the same thing I was.
Your code is correct and you are not loosing any records. In the SDK Documentation for ResultSet you can read that:
"A ResultSet object maintains a cursor pointing to its current row of data. Initially the cursor is positioned before the first row. The next method moves the cursor to the next row, and because it returns false when there are no more rows in the ResultSet object, it can be used in a while loop to iterate through the result set."
Only case were you could loose records if you do a resultSet.next() before the one you are showing.
Whenever next() is called, it reads a record from result set.
if (!set.next() ) {
System.out.println("no data");
} else {
do {
//statement(s)
} while (resultSet.next());
}
Related
I am getting a ResultSet of type ArrayList<MyClass> and all is working well, except it's not getting the first item from the list.
It seems this part is actually taking the first option and using it, despite not actually doing anything with it:
if (!result.next()) {
//throw Excepion
}
Then after that I run the while (result.next()) { and populate the ArrayList.
The first item in the database is just an empty String (well a space actually), and there are n other entries. I want the blank entry there too because this fills a JComboBox and need the first entry to always remain as a blank option.
But, because of checking if (!result.next()) before the while (result.next()), it will only show from item2 onwards. If I remove the if, it will leave the blank option in the dropdown.
Just to note, this code is using a try...finally.
So my issues/queries are:
1) Would I be best off removing the if (!result.next()) and just putting in a catch for the same exception?
2) Is it possible to use the initial way I described, but keeping the first entry in the result?
3) Is there a better way to get the first entry than just having a space in the first entry in the table? (Note that if it's just literally blank, and I remove the if, it will show a tiny little option in the dropdown table.
Taking all items from ResultSet and placing them in a list goes like this:
List<MyObj> data = new ArrayList<>();
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT Id, Name, ...");
while (rs.next()) {
int id= rs.getInt("Id");
String name = rs.getString("Name");
data.add(new MyObject(id, name));
}
} catch (SQLException e ) {
JDBCTutorialUtilities.printSQLException(e);
} finally {
if (stmt != null) { stmt.close(); }
}
You do not need to check the state of rs, because the check in the header of the while loop is sufficient.
Oracle's reference
You can check this way:
if(!rs.isBeforeFirst())
rs.isBeforeFirst() returns false if the resultset contains no rows.
When you call the next() function you allways jump to the following record, you must avoid the if(!result.next()), you can use if(result != null) and then, the loop
I am executing a Statement query and storing the data in ResultSet rs.
// if no record is returned by the query
if (!rs.next() ) {
Step1
}
// if atleast one record is returned by the query
if(rs.next()){
do {
if (rs.getString(1).equalsIgnoreCase("0")){
Step2
}
if (rs.getString(1).equalsIgnoreCase("1")){
Step3
}
} while (rs.next());
}
However if i am getting only a single record from the query then no steps are executed. It would be of great help if anyone can point out the mistake.
You have to understand what exactly next() method do. next() moves the cursor to next element. When you write next() inside if there the condition passed and there are no more elements when it comes to while.
And why don't you simplify your code by just doing
while ( rs.next() ) {
if (rs.getString(1).equalsIgnoreCase("0")){
Step2
}
if (rs.getString(1).equalsIgnoreCase("1")){
Step3
}
}
If you enter into while loop, there are items, otherwise No.
You are always skipping first element because you are calling .next() twice before taking an element.
Try doing something like this:
if (rs.next()) {
// At least one record returned
do {
if (rs.getString(1).equalsIgnoreCase("0")) {
// Step2
}
if (rs.getString(1).equalsIgnoreCase("1")) {
// Step3
}
} while (rs.next());
} else {
// No records returned
}
From JavaDoc ResultSet:
Moves the cursor froward one row from its current position. A ResultSet cursor is initially positioned before the first row; the first call to the method next makes the first row the current row; the second call makes the second row the current row, and so on.
In your code you don't need second invocation of rs.next() because cursor already on first row.
Initially rs contains one record or more precisely points to result set having one record.
Now when if(!rs.next()) is called then rs moves to the next record in result set which is not there as you have only one record. So this if goes well. But again when you use if(rs.next()) then rs won't be having any record, hence the if won't execute.
You should not call rs.next() method twice. Following logic should work:
if (!rs.next() ) {
Step1
}
else{ // if atleast one record is returned by the query
do {
if (rs.getString(1).equalsIgnoreCase("0")){
Step2
}
if (rs.getString(1).equalsIgnoreCase("1")){
Step3
}
}while (rs.next());
}
I'm implementing a software for a stock management system in java.I'm using MVC design pattern and i found this exception when trying to fill a JcomboBox. I want to get all the batches when a item-code is being passed into the method.so the method should return a array-list of relevant objects. but when I run this program it gave me this kinda error and it says there is empty result set. but i also tried the sql code manually in the terminal and it worked. so i can't imagine how to fix this error. i'm glad if anyone can tell me where is the problem. I tried to post my screen shots but it cannot be done as i don't have enough reputation
here is my code
String sql = "select batchNo from MainBatch where itemCode = ?";
Connection c=DBConnection.getInstance().getConnection();
PreparedStatement ps=c.prepareStatement(sql);
ps.setString(1, itemCode);
System.out.println(itemCode+" -----> item code is thiss");
ResultSet set=ps.executeQuery();
ArrayList<MainBatch> list=new ArrayList<>();
System.out.println(set.next()+" <-----result set is");
while (set.next()) {
MainBatch batch=new MainBatch(set.getString("batchNo"));
list.add(batch);
}
return list;
[
ResultSet.next() moves the result set's cursor to the next row. When you print it, before the while loop, you're losing the first row (or the only row in a single row result set). Personally, I'd just omit it, but if you have to have it, you could extract the result to a local variable:
boolean next = set.next();
System.out.println(next + " <-----result set is");
while (next) {
MainBatch batch=new MainBatch(set.getString("batchNo"));
list.add(batch);
next = set.next();
}
return list;
Remove this line.
System.out.println(set.next()+" <-----result set is");
You are calling set.next() twise, this moves the resultset pointer to next row.
My code belows doesnt work, just keep pointing the cursor at the first record, and when i try to replace the if statement with a while or for loop it just loops to the last record on my data table, when i click the button that performs the Action
Try {
string host="jdbc:derby://localhost:1527/Employees";
string uName="admin1";
string uPass="admin"
string SQL="SELECT * FROM Workers";
Connection con= DriverManager.getConnection(host, uName, uPass);
Statement stmt=Con.createStatement();
ResultSet=stmt.executeQuery(SQL);
if (rs.next())
{
string fname=rs.getString(first_name);
string lname=rs.getString(last_name):
txtFname.setText(fname);
txtLname.setText(lname);
}
else{
rs.previous();
//throw some sql error here}
}
catch(SQLException err) {
system.out.println(err.getMessage);
}
how do i get around this and get to a second, third,fourth to nth record successively (not simultaneously).
Looking at the ResultSet.next() doc, calling rs.next() once as an if condition will only move the cursor one position forward from its starting position. Hence, you only see the first record.
Replacing your if statement with either a while or for loop will cause the cursor to iterate through your entire result set. However, each iteration of the your current loop keeps overwriting the value of txtFname and txtLname with that of the "current" record. In order to capture the value of the 2nd, 3rd, 4th records etc... you will need to create a new TextComponent object at each iteration. For example,
// use some lists to capture intermediate records (for illustration only)
List<JTextComponent> allFnames = new ArrayList<JTextComponent>();
List<JTextComponent> allLnames = new ArrayList<JTextComponent>();
while(rs.next()) {
string fname=rs.getString(first_name);
string lname=rs.getString(last_name):
JTextComponent txtFname = new JTextComponent(); // new object
txtFname.setText(fname);
allFnames.add(txtFname);
JTextComponent txtLname = new JTextComponent(); // new object
txtLname.setText(lname);
allLnames.add(txtFname);
}
Now at the end of the while loop, the two lists will contain all your records.
javadoc says -
ResultSet#previous() -Moves the cursor to the previous row in this ResultSet
object.When a call to the previous method returns false, the cursor is positioned
before the first row. Any invocation of a ResultSet method which requires a
current row will result in a SQLException being thrown.
So in certain point of time your if(rs.next()) returns false then the else part executes and the cursor moves to the previous row in this ResultSet. Then When a call to the previous method returns false, the cursor is positioned before the first row. and then it will throw Exception
do it this way
if (!resultSet.next() ) {
System.out.println("resultset does not data");
} else {
do {
string fname=rs.getString(first_name);
string lname=rs.getString(last_name):
txtFname.setText(fname);
txtLname.setText(lname);
} while (resultSet.next());
}
One more thing check the comment of Nivedita and sort out the errors
So, a solution I created threw this exception: jdbc.SQLServerException: The result set has no current row on the line marked in the below code.
public String get64BitEncodedImageBySiteID(int siteID){
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection conn = DriverManager.getConnection(url, userName, password);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery( "SELECT SitePicture FROM SiteTable WHERE SiteID ="+siteID );
rs.next();
// The above line has since been moved to the if statement below where you can see it commented out,
// which prevents the exception from occuring but still doesn't fix the fact that the row is not being found.
if(/*rs.next() &&*/ rs.getBytes("SitePicture")!=null){ // EXCEPTION THROWN HERE!
byte ba[] = rs.getBytes("SitePicture");
return new sun.misc.BASE64Encoder().encodeBuffer(ba);
}
else {return null;}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
The method above, in the instance the exception was thrown, is taking a genuine siteID (22379) from an Entity object pulled directly from the same table. When using System.out.println(siteID); during this method, it declared that number to still be correct, ie still 22379. I've checked directly with the SQL server by running an identical statement in SQL Server, so I know the row exists in the table, but for some reason it is not being found. Image below.
So the problem is, the ResultsSet rs is not finding the row even though I know that it's there. Does anyone have any helpful insights?
Clarification: Just to be clear, I know that the ResultsSet contains no rows and that is why I am getting the exception. I also know that putting the rs.next() into the if statement will prevent the exception (as already stated in the comments). What is puzzling me is that the fact the ResultsSet contains no rows even though a row with the ID being parsed to it verifiably does exists because I have checked it directly with the SQL server.
This turned out to be a local mistake, but I'll post the solution anyway because this situation has some educational value.
As I've learned from #Ralph's comment to this answer, eliminating "the impossible" is a good way for such problems.
After avoiding the risk of siteID being wrong (by hardcoding it), we have a following situation:
the same exact query worked in one environment, but not the other, for only one particular SiteID, 2184
it's impossible that ResultSet just doesn't work for this particular value (I claim it is, because I always assume errors are in my code, not in language libraries)
if so, the databases must differ
Adding result statements inside while loop helped in my case.
while(rs.next) {
rs.getString("your column name");
}
The most likely explanation is that your ResultSet contains no rows. Have you checked that?
If that's the case, rs.next() will return false, but you are not checking the return value any more. Put rs.next() back into the if block, it was OK in there.
You can make sure by:
if (rs.next()) {
if(rs.getBytes("SitePicture")!=null){
byte ba[] = rs.getBytes("SitePicture");
return new sun.misc.BASE64Encoder().encodeBuffer(ba);
}
} else {
System.out.println("No rows returned");
}
EDIT:
what column type is siteID?
Your method takes an int, but your SQL wraps it in quotes, as if it were a string.
EDIT 2:
Using a PreparedStatement might solve your problem.
PreparedStatement ps = conn.prepareStatement("SELECT SitePicture FROM SiteTable WHERE SiteID = ?");
ps.setInt(1, siteId);
ResultSet rs = ps.executeQuery();
You may not get the result without checking whether the result has entries. For that use
while(rs.next()){
rs.getString("column name");
}
and try it. It worked fine for me.
Thanks