解决 JDBC 异常 “Cannot issue data manipulation statements with executeQuery()”

1、简介

本文将带你了解如何解决 JDBC 异常:“Cannot issue data manipulation statements with executeQuery()”。

在使用 JDBC 与数据库交互时,这个异常并不常见,但这个问题很容易解决。

2、理解异常

2.1、导致这个异常的原因

当我们尝试使用 executeQuery() 方法执行 INSERTUPDATEDELETE 语句时,就会出现错误 “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、导致该异常的场景

来看一个代码示例,以便更好地理解是什么触发了异常。如前所述,我们使用 MySQL 数据库。

首先,为示例创建一个简单的数据表:

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, USERNAME);
    insertStatement.setString(2, EMAIl);

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

3、解决问题

解决这种异常的方法很简单:必须针对要执行的 SQL 语句类型使用正确的方法。

这次,我们使用 executeUpdate() 方法来纠正上例中的做法。之后,查询数据库,以确认数据已被正确持久化。

测试修正后的代码:

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

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

    resultSet.next();
    assertEquals(USERNAME, resultSet.getString("username"));
    assertEquals(EMAIl, resultSet.getString("email"));
}

以下是 JDBC 各个 SQL 查询方法及其用途的简要概述:

方法 用途
executeQuery() 用于执行 SELECT 语句,从数据库中检索数据。
executeUpdate() 用于执行 INSERTUPDATEDELETE 等 DML 语句以及 CREATEALTER 等 DDL 语句。
execute() 用于执行任何 SQL 语句,通常是在未事先确定类型的情况下。

4、总结

本文介绍了在使用 JDBC 时出现 “Cannot issue data manipulation statements with executeQuery()” 异常的原因和解决办法,还介绍了 JDBC 每个 SQL 执行方法的区别。


Ref:https://www.baeldung.com/java-jdbc-executequery-dml-error