在 Java 中判断 JDBC 查询结果集是否为空,有多种方法。以下是几种常用的方式:

方法一:使用 next() 方法(最常用)

这是最直接和推荐的方法,因为结果集游标默认位于第一行之前。

import java.sql.*;

public class ResultSetEmptyCheck {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        
        try {
            // 建立数据库连接
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "username", "password");
            
            // 准备SQL语句
            String sql = "SELECT * FROM users WHERE age > ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, 18);
            
            // 执行查询
            rs = pstmt.executeQuery();
            
            // 方法1:直接使用 next() 判断
            if (!rs.next()) {
                System.out.println("结果集为空");
            } else {
                System.out.println("结果集不为空");
                // 处理第一行数据
                do {
                    String name = rs.getString("name");
                    int age = rs.getInt("age");
                    System.out.println("姓名: " + name + ", 年龄: " + age);
                } while (rs.next());
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (rs != null) rs.close();
                if (pstmt != null) pstmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

方法二:先判断再处理(避免跳过第一行)

如果你需要先判断是否为空,然后再处理数据:

public boolean isResultSetEmpty(ResultSet rs) throws SQLException {
    // 判断结果集是否为空,但不移动游标
    if (!rs.next()) {
        return true; // 结果集为空
    } else {
        rs.beforeFirst(); // 将游标移回初始位置
        return false; // 结果集不为空
    }
}

// 使用示例
try {
    ResultSet rs = pstmt.executeQuery();
    
    if (isResultSetEmpty(rs)) {
        System.out.println("没有找到匹配的记录");
        return;
    }
    
    // 处理结果集
    while (rs.next()) {
        // 处理每一行数据
        System.out.println(rs.getString("column_name"));
    }
} catch (SQLException e) {
    e.printStackTrace();
}

方法三:使用 isBeforeFirst() 方法(更优雅的方式)

public boolean isResultSetEmpty(ResultSet rs) throws SQLException {
    return !rs.isBeforeFirst() && rs.getRow() == 0;
}

// 或者更简单的方式
public boolean isEmptyResultSet(ResultSet rs) throws SQLException {
    if (rs.isBeforeFirst()) {
        // 结果集有数据
        return false;
    } else {
        // 结果集为空
        return true;
    }
}

方法四:封装工具类

你可以封装一个工具类来简化判断:

public class JdbcUtils {
    
    /**
     * 判断结果集是否为空
     */
    public static boolean isEmpty(ResultSet rs) throws SQLException {
        return rs == null || !rs.isBeforeFirst();
    }
    
    /**
     * 获取结果集的行数
     */
    public static int getRowCount(ResultSet rs) throws SQLException {
        if (rs == null) return 0;
        
        int rowCount = 0;
        if (rs.last()) {
            rowCount = rs.getRow();
            rs.beforeFirst(); // 重置游标到开始位置
        }
        return rowCount;
    }
    
    /**
     * 安全地处理结果集
     */
    public static void processResultSet(ResultSet rs, ResultSetProcessor processor) throws SQLException {
        if (isEmpty(rs)) {
            System.out.println("结果集为空");
            return;
        }
        
        while (rs.next()) {
            processor.process(rs);
        }
    }
    
    public interface ResultSetProcessor {
        void process(ResultSet rs) throws SQLException;
    }
}

// 使用工具类
try {
    ResultSet rs = pstmt.executeQuery();
    
    // 判断是否为空
    if (JdbcUtils.isEmpty(rs)) {
        System.out.println("查询结果为空");
        return;
    }
    
    // 获取行数
    int rowCount = JdbcUtils.getRowCount(rs);
    System.out.println("找到 " + rowCount + " 条记录");
    
    // 处理结果集
    JdbcUtils.processResultSet(rs, new JdbcUtils.ResultSetProcessor() {
        @Override
        public void process(ResultSet rs) throws SQLException {
            System.out.println("ID: " + rs.getInt("id") + ", Name: " + rs.getString("name"));
        }
    });
    
} catch (SQLException e) {
    e.printStackTrace();
}

方法五:使用 try-with-resources(Java 7+)

对于现代 Java 开发,推荐使用 try-with-resources 自动管理资源:

public void checkUserExists(int minAge) {
    String sql = "SELECT id, name FROM users WHERE age > ?";
    
    try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "user", "pass");
         PreparedStatement pstmt = conn.prepareStatement(sql)) {
        
        pstmt.setInt(1, minAge);
        
        try (ResultSet rs = pstmt.executeQuery()) {
            if (!rs.next()) {
                System.out.println("没有找到年龄大于 " + minAge + " 的用户");
                return;
            }
            
            System.out.println("找到以下用户:");
            do {
                System.out.printf("ID: %d, 姓名: %s%n", 
                    rs.getInt("id"), rs.getString("name"));
            } while (rs.next());
        }
        
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

最佳实践建议

  1. 首选方法一:直接使用 if (!rs.next()) 判断,简单明了
  2. 使用 try-with-resources:确保资源正确关闭
  3. 避免多次调用 next():每次调用都会移动游标
  4. 考虑使用 ORM 框架:如 MyBatis、Hibernate 等,可以减少手动处理 ResultSet 的麻烦

常见错误示例

// 错误:多次调用 next() 会跳过第一行
if (rs.next()) {  // 这里移动了游标
    // 处理数据时又从第一行开始,但实际上已经指向第二行了
    while (rs.next()) {  // 这会跳过第一行!
        // ...
    }
}

// 正确:使用 do-while 或者先判断再重置
if (rs.next()) {
    do {
        // 处理当前行
    } while (rs.next());
}

总结:最推荐使用第一种方法,因为它最直接、效率最高,也是最常见的写法。

Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。

更多推荐