遗留项目中未调用next()直接读取ResultSet是否正确?技术问询
Great question—this is a classic JDBC pitfall that trips up even experienced developers from time to time. Let's break this down clearly:
The Core Issue: ResultSet Cursor Position
By JDBC specification, a ResultSet object's cursor starts positioned before the first row of the result set. That means you must call a navigation method like next() (or first(), though next() is the standard choice here) to move the cursor to the first (and in this case, only) row before you can read any data from it.
Analyzing the Legacy Code
Your observation is spot-on: the code as written skips calling next() and tries to read resultSet.getInt(1) immediately. In most standard JDBC drivers (like those for PostgreSQL, MySQL, or Oracle), this will throw an SQLException with a message along the lines of "ResultSet not positioned properly" or "Invalid cursor state".
While it's true that COUNT(*) will always return exactly one row (even if the table is empty, it returns 0), the JDBC spec doesn't make an exception for this case—you still need to position the cursor correctly. There might be some extremely old or non-compliant drivers that behave differently, but relying on that is risky and non-portable.
The Correct Implementation
Here's how to fix the method properly, adhering to JDBC standards:
public int getCount(String tableName, Connection connection) throws SQLException { try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT COUNT (*) FROM " + tableName)) { // Move cursor to the first (and only) result row if (resultSet.next()) { return resultSet.getInt(1); } // COUNT(*) will always return a row, so this is just a safe fallback return 0; } }
Extra Security Note
As a side point: this method directly concatenates tableName into the SQL query, which is a critical SQL injection vulnerability. If tableName comes from user input or an untrusted source, an attacker could execute arbitrary SQL on your database. For a safer approach, consider using a PreparedStatement with proper validation of the table name (since table names can't be parameterized directly, you'll need to whitelist valid table names).
内容的提问来源于stack exchange,提问作者Oleg Zinoviev

