Java 我真的可以通过闭合连接读取LOB吗?
我使用wildfly-8.2.0.Final。此服务器上存在连接池(Oracle)。 请看以下代码: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&
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);
}