Java
ResultSet
Database Programming
SQL Queries
Java Database Connectivity

Java ResultSet how to check if there are any results

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The standard way to check whether a JDBC ResultSet contains any rows is to call next(). That method both answers the question and advances the cursor to the first row when data exists, which is why the surrounding iteration pattern matters.

Why next() Is the Normal Answer

A ResultSet starts before the first row. There is no universal row-count property you inspect first. Instead, you ask JDBC to move to the next row.

java
1import java.sql.Connection;
2import java.sql.PreparedStatement;
3import java.sql.ResultSet;
4
5public class Main {
6    public static void printUsers(Connection connection) throws Exception {
7        String sql = "select id, username from users";
8
9        try (PreparedStatement ps = connection.prepareStatement(sql);
10             ResultSet rs = ps.executeQuery()) {
11
12            if (!rs.next()) {
13                System.out.println("No rows found");
14                return;
15            }
16
17            do {
18                long id = rs.getLong("id");
19                String username = rs.getString("username");
20                System.out.println(id + " " + username);
21            } while (rs.next());
22        }
23    }
24}

This pattern works because once the first next() returns true, the cursor is already positioned on the first row.

The if Plus do/while Pattern

That if plus do/while structure is the safest general-purpose shape when you need to both check for emptiness and then process rows.

Why not a plain while (rs.next()) loop? Because if you also call next() earlier just to check for existence, the first row gets consumed and then skipped in the loop.

That mistake is very common.

If You Only Need Existence, Ask the Database More Directly

Sometimes the real requirement is not to iterate rows at all. You only need a yes-or-no answer. In that case, shape the SQL for existence.

java
1import java.sql.Connection;
2import java.sql.PreparedStatement;
3import java.sql.ResultSet;
4
5public class Main {
6    public static boolean userExists(Connection connection, String username) throws Exception {
7        String sql = "select 1 from users where username = ?";
8
9        try (PreparedStatement ps = connection.prepareStatement(sql)) {
10            ps.setString(1, username);
11
12            try (ResultSet rs = ps.executeQuery()) {
13                return rs.next();
14            }
15        }
16    }
17}

This avoids pulling unnecessary columns when all the application needs is existence.

What About isBeforeFirst()?

You may see ResultSet.isBeforeFirst() used to detect whether rows exist.

java
if (rs.isBeforeFirst()) {
    System.out.println("There is at least one row");
}

That can work in some cases, but it is not the most portable or useful primary answer. next() is the standard iteration mechanism that you already need for normal processing, so it remains the simplest and most reliable pattern.

Forward-Only Result Sets Change the Mindset

Many JDBC result sets are forward-only streams. That means cursor movement is part of reading the data, not a side operation you can undo cheaply.

Once you accept that model, the next()-based pattern feels natural:

  • call next() to see whether the first row exists,
  • process that row if it does,
  • continue iterating from there.

Trying to inspect row existence without engaging with cursor movement often leads to more complicated code than necessary.

Keep the SQL Intent Aligned With the Java Intent

If the Java code only needs to know whether anything exists, do not write a large select * query. If the Java code needs the rows, do not write existence-style SQL and then issue a second query unnecessarily.

The cleanest programs keep the SQL and the Java consumption pattern aligned.

Common Pitfalls

A common mistake is calling rs.next() once to check for data and then starting a separate while (rs.next()) loop. That skips the first row.

Another issue is expecting the ResultSet to expose a reliable row count before iteration. Many JDBC drivers are optimized for streaming, not for pre-counting.

Developers also sometimes use isBeforeFirst() as if it were a better general answer than next(), even though next() is usually both simpler and more portable.

Summary

  • Use rs.next() to check whether a ResultSet has any rows.
  • If it returns true, the cursor is already positioned on the first row.
  • Use an if plus do/while pattern when you need to process rows after the emptiness check.
  • Shape the SQL as an existence query when the application only needs a boolean answer.
  • Avoid patterns that accidentally skip the first row.

Course illustration
Course illustration

All Rights Reserved.