`ResultSet.isBeforeFirst`抛出`NullPointerException`异常,原因令人意外。

huangapple go评论75阅读模式
英文:

ResultSet.isBeforeFirst throws NullPointerException unexpectedly

问题

private ResultSet getResultSet(String id) {
    RDSPooledConnector rdsPooledConnector = connector.getConnector(endpoint, port);
    try (Connection connection = rdsPooledConnector.getConnection();
         PreparedStatement preparedStatement = connection.prepareStatement(query)) {
        preparedStatement.setString(1, id);
        return preparedStatement.executeQuery();
    } catch (SQLException exception) {
        LOGGER.error("无法检索结果集 {}", id, exception);
        return null;
    }
}

@Override
public boolean shouldMove(String id) {
    try {
        ResultSet resultSet = getResultSet(id);
        return resultSet != null && resultSet.isBeforeFirst(); // 此行!
    } catch (SQLException exception) {
        LOGGER.error("失败: {}", id, exception);
        return false;
    }
}

堆栈跟踪为:

java.lang.NullPointerException: 空值
	at com.mysql.jdbc.ResultSetImpl.isBeforeFirst(ResultSetImpl.java:6104)
	at com.zaxxer.hikari.pool.HikariProxyResultSet.isBeforeFirst(HikariProxyResultSet.java)

我在抛出 NPE 的那一行加了注释。我想知道为什么会出现这种情况,考虑到 ResultSetgetResultSet 方法的 try 块之后被访问。因此,我假设当到达调用 isBeforeFirst 的那行代码时,连接已关闭,即使多个线程调用此方法,每个线程都会有自己的连接。

下面是 ResultSetImpl.java 中的 isBeforeFirst 方法的代码:

public boolean isBeforeFirst() throws SQLException {
    synchronized (checkClosed().getConnectionMutex()) {
        return this.rowData.isBeforeFirst();
    }
}

显然,rowData 为 null。但我不明白为什么会出现这种情况。


<details>
<summary>英文:</summary>

I have the following code: 

private ResultSet getResultSet(String id) {
    RDSPooledConnector rdsPooledConnector = connector.getConnector(endpoint, port);
    try (Connection connection = rdsPooledConnector.getConnection();
         PreparedStatement preparedStatement = connection.prepareStatement(query)) {
        preparedStatement.setString(1, id);
        return preparedStatement.executeQuery();
    } catch (SQLException exception) {
        LOGGER.error(&quot;Failed to retrieve result set {}&quot;, id, exception);
        return null;
    }
}


@Override
public boolean shouldMove(String id) {
    try {
        ResultSet resultSet = getResultSet(id);
        return resultSet != null &amp;&amp; resultSet.isBeforeFirst(); // THIS LINE!
    } catch (SQLException exception) {
        LOGGER.error(&quot;Failed: {}&quot;, id, exception);
        return false;
    }
}

I commented on the line that throws NPE. The stack trace is: 

java.lang.NullPointerException: null
at com.mysql.jdbc.ResultSetImpl.isBeforeFirst(ResultSetImpl.java:6104)
at com.zaxxer.hikari.pool.HikariProxyResultSet.isBeforeFirst(HikariProxyResultSet.java)


I&#39;m wondering why this could happen, considering that the `ResultSet` is being accessed after the `try` block in `getResultSet` method. So I assume  the connection is closed when it gets to the line where `isBeforeFirst` is called, and even if multiple threads call this method, each will have its own connection.


This is the code for `ResultSetImpl.java`&#39;s `isBeforeFirst`: 

public boolean isBeforeFirst() throws SQLException {
    synchronized (checkClosed().getConnectionMutex()) {
        return this.rowData.isBeforeFirst();
    }
}

Apparently `rowData` is null. But I don&#39;t understand why.

</details>


# 答案1
**得分**: 2

`ResultSet`对象实际上不应在方法之间传递。@dan1st的评论正中要害。在`getResultSet()`方法中,您关闭了`PreparedStatement`,因此也关闭了`ResultSet`。如果您真的想在方法之间传递结果集,请考虑使用[javax.sql.CachedRowSet][1]。

<details>
<summary>英文:</summary>

`ResultSet` objects should not really be passed between methods. The comment by @dan1st hit the nail on the head. In method `getResultSet()` you close the `PreparedStatement` and therefore you close the `ResultSet`. If you really want to pass a result set between methods, consider [javax.sql.CachedRowSet][1]


  [1]: https://docs.oracle.com/javase/8/docs/api/javax/sql/rowset/CachedRowSet.html

</details>



huangapple
  • 本文由 发表于 2020年9月3日 02:13:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/63711367.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定