我能通过封闭连接真正读取LOB吗?

时间:2015-03-26 06:46:30

标签: java oracle inputstream connection-pooling wildfly

我使用wildfly-8.2.0.Final。此服务器上有连接池(Oracle)。 请看下面的代码:

public ArrayList<HashMap<String, Object>> fetchSome(String query)
        throws OracleQueryProcessorException {
    ArrayList<HashMap<String, Object>> result = new ArrayList<HashMap<String, Object>>();
    try {
        Context initCtx = new InitialContext();
        DataSource ds = (DataSource) initCtx.lookup(driver);
        try (Connection con = ds.getConnection();
                PreparedStatement stmt = con.prepareStatement(query)) {
            try (ResultSet rs = stmt.executeQuery()) {
                ResultSetMetaData rsmd = rs.getMetaData();
                rs.next();
                HashMap<String, Object> row = new HashMap<String, Object>();
                String name = rsmd.getColumnName(1);
                Object value = rs.getObject(1);
                if (value instanceof Blob) {
                    Blob bl = (Blob) value;
                    if (bl.length() > 0)
                        value = bl.getBinaryStream();
                    else
                        value = null;
                }
                row.put(name, value);
                result.add(row);
            }
        } catch (SQLException e) {
            throw new OracleQueryProcessorException();
        }
    } catch (NamingException e) {
        throw new OracleQueryProcessorException();
    }
    return result;
}

这是这个功能的用法:

InputStream is = (InputStream) fetchSome("SELECT BLOB_FIELD FROM TEST WHERE ID = 1").get(0).get("BLOB_FIELD");
            if (is != null) {
                byte[] a = new byte[3];
                is.read(a);
            }

从这个流中读取是有效的!!它怎么样?连接已关闭(因为使用try-with-resources子句)。从这个流中读取不会从池中获取任何连接(所有池的连接都可用)。

2 个答案:

答案 0 :(得分:0)

fetchSome()打开Connection,发送查询,然后将数据读回到生成的ArrayList中。然后fetchSome关闭Connection并返回ArrayList。您感兴趣的代码会从返回的ArrayList中读取,而不是从您正确注意到的Connection开始关闭。

当您的方法返回时,所有数据库通信都已完成,并且所有数据都已复制到返回的列表中,然后可以根据需要随时读取它,而不需要{{1再次。

答案 1 :(得分:0)

它真的适用于各种BLOB尺寸吗?好的门槛是:

  • 4000B(限制BLOB可能在行中排列 - 不存放在一边)
  • 2000B(RAW的最大大小) - BLOB可以在某处投射到RAW
  • 16KB,32KB
  • 比JVM堆大小更大的值

OCI级别的AFAIK(C客户端库)LOB可能是“预先分配”的.i.e。 BLOB的一小部分可以发送给客户端,尽管客户端尚未请求。这应该减少数据库和客户端之间的往返次数。

此外,您应该尝试检查v $ instance视图以检查连接是否确实已关闭。有时JDBC和Oracle之间的合作很棘手。

例如,通过Connection.createBLOB()创建的临时LOB与数据库的任何其他临时lobs不同。我认为这是因为Oracle数据库无法与JVM GC通信,并且它不知道Java实例何时被处理掉了。所以这些lobs“永远”保存在数据库中。