当使用 JDBC 检索查询结果时,我使用 ResultSet,例如:
ResultSet result_set = statement.executeQuery(query);
在文档中它说:“ResultSet 对象维护一个指向其当前数据行的游标。”这意味着如果我在解析查询结果之前执行result_set.close()
,我就会丢失它们。如果我立即解析 ResultSet 中的数据,我将在解析过程中保持与数据库的连接。我想尽量减少时间,我想在不连接到数据库的情况下解析查询结果。
有没有一种方法可以在解析结果之前关闭与数据库的连接来存储查询数据?
例如这样的事情:
Connection connection = DriverManager.getConnection(url, username, password);
Statement statement = connection.createStatement();
ResultSet result_set = statement.executeQuery(query);
// store data retrieved from query
result_set.close();
statement.close();
connection.close();
// do something with stored data
RowSet
javax.sql.rowset
包扩展了ResultSet
,增加了各种功能。
CachedRowSet
将行的数据复制到内存中。引用文档:
对象是数据行的容器,将其行缓存在内存中,这使得无需始终连接到其数据源即可进行操作。CachedRowSet
…
对象是断开连接的行集,这意味着它仅短暂地使用与其数据源的连接。CachedRowSet
问题是找到一个有能力的接口具体实现。 Oracle 提供了 Sun 时代的开源参考实现。但是,正如我所记得的(我可能是错的),该实施有一些未解决的限制或缺陷。一定要彻底测试。
用极简主义的方法填补你的代码片段中的空白:
final var rowLength =
result_set
.getMetaData()
.getColumnCount();
final var resultCache = Stream.<Object[]>builder();
while ( result_set.next() )
{
final var row = new Object[ rowLength ];
for ( int index=1; index<=rowLength; index++ )
{
row[index] = result_set.getObject( index );
}
resultCache.accept( row );
}
record MyData( Integer value, String text )
{
// ... transformation could be placed in here with alternative constructor
}
final var results =
resultCache.build()
.map( row -> new MyData( (Integer) row[0],
(String) row[1] ) )
.toList();
这假设您知道返回数据中的顺序以及稍后执行“解析”/等的类型。 考虑“解析”和内存占用等所需的计算时间是熟悉框架行为的好方法。我建议尝试不同大小的结果集(在数量和行上)和解析/转换的复杂性。也许看看 jpa-implementation 有助于理解可能的解决方案。
在这篇文章中,可以找到有关结果提取的更多详细信息:How to fetch entire row as array of objects with JDBC