在查询 Oracle 的错误时,是不是有任何避免 Stream 的解决方法已经关闭?
Posted
技术标签:
【中文标题】在查询 Oracle 的错误时,是不是有任何避免 Stream 的解决方法已经关闭?【英文标题】:Any workaround to avoid Stream has already closed when query for Oracle's bug?在查询 Oracle 的错误时,是否有任何避免 Stream 的解决方法已经关闭? 【发布时间】:2021-07-09 04:09:27 【问题描述】:我使用 ojdbc8 版本 21.1.0.0 作为我的 JDBC。我遇到的问题是每次调用close()
之前我的连接流都会关闭,当我执行我的查询时,由于未知原因从resultSet 请求了很长时间,并且我的SQL 在SQL 开发人员上运行良好。所以我用谷歌搜索并看到这个错误报告在 Oracle 上。
https://support.oracle.com/knowledge/Middleware/832903_1.html
这似乎是他们的 JDBC 的错误?有谁知道哪个版本的 ODBC8 没有这个 bug?或其他解决方法来避免此错误?
==== 更新 ====
@斯蒂芬·C
好吧,如果你这么说。但我认为这无论如何都无济于事,因为代码本身太简单了,不会有这样的错误。
class Channel
private static DataSource ds = null;
private static final String GET_ONE = "SELECT * FROM Channel WHERE Id=?";
public Channel()
if(ds == null)
try
Context ctx = new InitialContext();
ds = (DataSource) ctx.lookup("jdbc/oracle");
catch (NamingException e)
e.printStackTrace();
public HashMap<String, Object> getOne(String id) throws SQLException
HashMap<String, Object> result = null;
ResultSet rs = null;
try(Connection conn = ds.getConnection();
PreparedStatement pstmt = con.prepareStatement(GET_ONE);)
pstmt.setString(1, id);
rs = pstmt.executeQuery();
if(rs.next())
result = new HashMap<String, Object>();
result.put("Time_Limit", rs.getLong("Time_Limit"));// recommended by @tgdavies
result.put("Id", rs.getString("Id"));
result.put("Name", rs.getString("Name"));
catch(SQLException e)
throw e;
finally
if(rs != null)
try
rs.close();
catch(SQLException e)
return result;
【问题讨论】:
如果您使用的是非常旧的驱动程序版本,请升级。如果您使用的是最新版本,并且看起来有问题,请提交报告并降级到之前最近的稳定版本。 您是否尝试过在任何其他列之前先从 ResultSet 读取 LONG 值的解决方案?见blog.jooq.org/2015/12/30/… @tgdavies 尝试先读取 Long 值,但仍然出现该错误 @TimBiegeleisen 试图降级到 19.7.0.0,但现在没有运气 真正的原因很可能是>您的minimal reproducible example。 【参考方案1】:我想我知道问题出在哪里了。
(警告:您没有包含堆栈跟踪,所以我无法确认这一点。此外,您发布的链接未打开,因此我们无法看到您正在谈论的错误报告的详细信息。)
try(Connection conn = ds.getConnection();
PreparedStatement pstmt = con.prepareStatement(GET_ONE);)
pstmt.setString(1, id);
rs = pstmt.executeQuery();
if(rs.next())
result = new HashMap<String, Object>();
result.put("Time_Limit", rs.getLong("Time_Limit"));// recommended by @tgdavies
result.put("Id", rs.getString("Id"));
result.put("Name", rs.getString("Name"));
catch(SQLException e)
throw e;
finally
if(rs != null)
try
rs.close();
catch(SQLException e)
问题是finally
在资源自动关闭后执行。因此,您的代码将在PreparedStatement
关闭后调用rs.close()
。但关闭语句会关闭从该语句创建的任何结果集。
参考:
Are resources closed before or after the finally?可能的解决方案:
-
也将
ResultSet
视为资源;例如使用嵌套的尝试使用资源。
摆脱finally
...
【讨论】:
我不明白的东西:我已经忽略了这一行 catch(SQLException e)
,所以我不认为在执行它时会出现流关闭异常。对吗?
嗯......从堆栈跟踪中应该清楚SQLException
被抛出的位置。它可能发生在 try 块中,这会使我的解释不正确。 (但 minrep 应该包含一个堆栈跟踪...)
如果这确实是一个驱动程序错误,那么您应该与 Oracle 支持人员讨论解决方法和替代版本。
这看起来是正确的答案。删除 finally 块。你不需要它。以上是关于在查询 Oracle 的错误时,是不是有任何避免 Stream 的解决方法已经关闭?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Data Studio 查询 BigQuery 时如何避免错误?
在ORACLE触发器中想使用into 语句给一个变量赋值,但是查询出来的值可能为空,如何避免报错未找到任何数据