JDBC ResultSet — Iterating Query Results
Fast recall
Quick revision
Core answer
false when rows run out) and getXxx("col") to read columns. It's forward-only by default and must be closed.Whether you know ResultSet is a cursor and the next()/getXxx iteration loop.
Reading a column before calling next(), or assuming it's a loaded list.
Note the cursor starts before row 1 and ResultSet is forward-only by default.
Interview-ready guide
Interview answer
A ResultSet is a cursor over the rows that a query returns.
It's important to understand it's a cursor, not a fully loaded list in memory; it points at one row at a time. The cursor starts positioned before the first row, which is the key detail people forget. So to read data, you first call next, which moves the cursor to the next row and returns true if there's a row there, or false when you've run off the end.
That's why the standard pattern is a while loop on rs dot next. Inside the loop, you read each column with the typed getters, like getInt and getString, and you can read either by column name, which is more readable, or by a one-based column index.
By default a ResultSet is forward-only, meaning you iterate through it once from start to finish, and it's tied to the Statement and Connection that produced it, so once those are closed the ResultSet is invalid. That's why you close it when you're done, ideally with try-with-resources.
The mistakes to avoid are trying to read a column before calling next, since the cursor starts before the first row, treating the ResultSet like a reusable list, and using zero-based column indices when they're actually one-based.
JDBC ResultSet — Iterating Query Results
Direct Answer
A ResultSet is a cursor over the rows returned by a query. It starts positioned before the first row; you call next() to advance (it returns false when rows run out) and getXxx("col") to read columns. It's forward-only by default and must be closed.
Deep Dive & Architecture
A ResultSet represents the rows produced by a statement and maintains a cursor position. The cursor begins before row one. Each successful call to next() moves it forward and makes that row available through getters such as getLong, getString, or getObject. When next() returns false, no rows remain.
For example, while (rs.next()) can map every row into a domain object using column labels. SQL NULL needs care: primitive getters return a default primitive value, so call wasNull() when zero or false could be meaningful, or use a suitable object getter. A result set belongs to its statement and connection, so all three should be closed with try-with-resources and not returned outside that scope.
Code Example
String sql = "SELECT id, name FROM users WHERE active = ?";
try (PreparedStatement ps = con.prepareStatement(sql)) {
ps.setBoolean(1, true);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) { // advance; false when done
int id = rs.getInt("id"); // read by column name
String name = rs.getString("name");
System.out.println(id + ": " + name);
}
}
}
// cursor started BEFORE row 1, so next() must be called before reading
Common Mistakes & Pitfalls
- Reading before
next(): the cursor starts before the first row — always callnext()first. - Treating it as a list: it's a forward cursor, read once.
- Using it after closing the Statement/Connection: the ResultSet becomes invalid.
- 0-based column index: indices are 1-based (
getInt(1)).
Check your understanding
Answer these without looking back at the article.
- How do you check for NULL values when reading from a ResultSet?
- How do you map ResultSet rows to Java objects in JDBC?
- What happens if you do not close a ResultSet in JDBC?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.