1. 引言

本文将探讨如何解决一个常见的JDBC异常:*Cannot issue data manipulation statements with executeQuery()*。虽然在使用JDBC操作数据库时不常遇到这个问题,但幸运的是,它的解决方案非常直接。

2. 理解异常

错误信息本身已经提示了问题所在,但让我们深入分析一下根本原因。

2.1. 异常含义

当我们的代码尝试使用executeQuery()方法执行INSERT、UPDATE或DELETE语句时,就会抛出*Cannot issue data manipulation statements with executeQuery()*异常。

⚠️ 关键点StatementPreparedStatement对象的executeQuery()方法专门用于处理SELECT查询。查看方法签名会发现,它返回一个ResultSet实例,用于存放从数据库检索的行数据。

这个异常通常在使用Connector/J连接MySQL时出现,但其他数据库也有相同规则,只是错误信息可能略有不同。在新版MySQL Connector/J中,错误信息已更新为

java.sql.SQLException: Statement.executeQuery() cannot issue statements that do not produce result sets.

2.2. 触发异常的常见场景

通过代码示例理解触发条件。首先创建测试表:

CREATE TABLE IF NOT EXISTS users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50),
    email VARCHAR(50)
)

现在尝试执行非SELECT语句。以下测试用例通过INSERT语句验证异常抛出:

@Test
void givenInsertSql_whenExecuteQuery_thenAssertSqlExceptionThrown() throws SQLException {
    String insertSql = "INSERT INTO users (username, email) VALUES (?, ?)";
    PreparedStatement insertStatement = connection.prepareStatement(insertSql);
    insertStatement.setString(1, "john_doe");
    insertStatement.setString(2, "john@example.com");

    SQLException exception = assertThrows(SQLException.class, insertStatement::executeQuery);
    assertEquals("Statement.executeQuery() cannot issue statements that do not produce result sets.", exception.getMessage());
}

3. 解决方案

解决这个异常很简单:必须根据SQL语句类型选择正确的执行方法

以之前的INSERT语句为例,这次改用executeUpdate()方法,然后查询数据库验证数据持久化:

@Test
void givenInsertSql_whenExecuteUpdate_thenAssertUserSaved() throws SQLException {
    String insertSql = "INSERT INTO users (username, email) VALUES (?, ?)";
    PreparedStatement insertStatement = connection.prepareStatement(insertSql);
    insertStatement.setString(1, "john_doe");
    insertStatement.setString(2, "john@example.com");
    insertStatement.executeUpdate();

    String selectSql = "SELECT * FROM users WHERE username = ?";
    PreparedStatement selectStatement = connection.prepareStatement(selectSql);
    selectStatement.setString(1, "john_doe");
    ResultSet resultSet = selectStatement.executeQuery();

    resultSet.next();
    assertEquals("john_doe", resultSet.getString("username"));
    assertEquals("john@example.com", resultSet.getString("email"));
}

以下是JDBC核心方法的功能对比:

方法 用途
executeQuery() ✅ 执行SELECT查询,返回ResultSet
executeUpdate() ✅ 执行DML语句(INSERT/UPDATE/DELETE)和DDL语句(CREATE/ALTER)
execute() ⚠️ 执行任意SQL语句,适用于语句类型不确定的场景

4. 结论

本文分析了JDBC中不常见的*Cannot issue data manipulation statements with executeQuery()*异常及其成因。核心要点是:必须根据SQL语句类型选择正确的JDBC方法,因为每个方法都有其特定用途。简单粗暴地记住:查询用executeQuery(),增删改用executeUpdate(),不确定时用execute()