Java 我真的可以通过闭合连接读取LOB吗?

Java 我真的可以通过闭合连接读取LOB吗?,java,oracle,inputstream,connection-pooling,wildfly,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&

我使用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;
}
从这个流中读取正在工作!!它是如何工作的?连接已关闭(因为使用了try with resources子句)。从该流读取时,不会从池中获取任何连接(所有池的连接都可用)。

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


当您的方法返回时,所有数据库通信都已完成,所有数据都已复制到返回的列表中,然后可以从该列表中随时读取数据,而无需再次连接。

它真的适用于各种大小的BLOB吗?好的阈值是:

  • 4000B(BLOB可能在行中排列的限制-不存储在一旁)
  • 2000B(原材料的最大尺寸)-BLOB可以铸造成原材料
  • 16KB,32KB
  • 一些比JVM堆大的巨大值
OCI级别(C客户端库)LOB上的AFAIK可能是“预分配的”。BLOB的一小部分可以发送给客户机,尽管客户机尚未请求它。这将减少数据库和客户端之间的往返次数

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


例如,通过Connection.createBLOB()创建的临时LOB的处理方式与数据库对任何其他临时LOB的处理方式不同。我认为这是因为Oracle数据库无法与JVMGC通信,并且它不知道java实例是何时被释放的。因此,这些LOB“永远”保存在数据库中

当我执行bl.getBinaryStream()时,我并没有从blob读取数据,我只是获取InputStream对象。当连接关闭时,LOB内容还没有从DB读取。我已经读取了250MB LOB,并且没有看到对JVM使用内存的任何影响。我在读取时尝试删除表。读取已停止:)我想我的意思是读取实际上从blob而不是jvm内存中获取数据。这也很奇怪。Oracle不应允许您在某些光标碰到表时将其放下。
连接con
的确切类型是什么。可能是某个PooledConnection(不是OracleConnection)并对其调用close,只会使其返回到连接池中。这确实是一个极端情况,每个JDBC dirver版本的行为都可能不同。删除表时会出现什么ORA-XXX错误?
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);
            }