Java 如何以原子方式运行2 SQL“SELECT”?或者在我处理行之前获取行数的其他更好的方法

Java 如何以原子方式运行2 SQL“SELECT”?或者在我处理行之前获取行数的其他更好的方法,java,database,jdbc,derby,h2,Java,Database,Jdbc,Derby,H2,我正在尝试原子化运行 ResultSet resSet; resSet = statement.executeQuery("SELECT COUNT(*) FROM table"); resSet.next() long rowCount = resSet.getLong(1); resSet = statement.executeQuery("SELECT * FROM table"); // read data of known row count... 我的问题是什么是最好的方法 目前我

我正在尝试原子化运行

ResultSet resSet;
resSet = statement.executeQuery("SELECT COUNT(*) FROM table");
resSet.next()
long rowCount = resSet.getLong(1);
resSet = statement.executeQuery("SELECT * FROM table");
// read data of known row count...
我的问题是什么是最好的方法

目前我发现我可以做到:

connection.setAutoCommit(false);
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE)
// call 2 SQL queries above
connection.commit();
这种方法似乎有效。我测试了在第一次选择和提交之间阻止另一个线程执行插入。 这是正确的最佳方式吗?我是否可以确保这样我的计数将始终与下一次选择返回的行数相同

此外,我还希望Connection.TRANSACTION_SERIALIZABLE代替Connection.TRANSACTION_REPEATABLE_READ就足够了。 但它在Derby 10.11.1.1中不起作用。是虫子吗?我对数据库业务还不熟悉,但它在H2数据库中的工作情况与预期的一样-因此我认为它可能是一个derby bug

请注意,我已经了解了解决方案,您可以在其中执行以下操作:

statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 
                                 ResultSet.CONCUR_READ_ONLY);
resultSet = statement.executeQuery("SELECT * FROM table");
if (ResultSet.last()) {
    int rowCount = ResultSet.getRow();
    ResultSet.beforeFirst(); 
}
while(ResultSet.next()){...}
但这个解决方案不是最优的。对于德比,我测得速度慢了约7倍。对于H2,速度大约慢2倍。

怎么样

SELECT (SELECT COUNT(*) FROM table) c, * FROM table

为什么不简单地执行第二个查询,并为每个读取行增加一个计数器呢?另请注意,有趣的是,当connection.commit在executeQuery之后,resultSet.next之前时,H2数据库将正确打印结果。但Derby数据库将为您提供修改后的数据。因此,在Derby中,为了使其原子化工作,您需要在从ResultSetTransf中读取数据后放入commit。很显然,我不太关心这种用例的隔离。假设您运气不好,在count查询和第二个查询之间添加了一行。那又怎么样?处理第n-1个元素时,进度条将为100%,而不是99.999%。这真的是个问题吗?@VitBernatik在定义url连接时,您可以使用所有应用程序的这些参数初始化连接,因此根本不需要调用ConnectionsetAutocommit或ConnectionsetTransactionIsolation,所有连接都将这样创建。此外,最好只调用第二个查询,并使用计数器变量检查得到的行数,而不是执行两次相同的繁重查询。这是非常重要的数据库版本、设置、特定于驱动程序的序列化工作情况和效率。我会不惜一切代价避免它。哇,谢谢。但我不确定它的开销是否太大。假设我有1M行,每行我都会复制这个计数,而我只需要一次计数。它也适用于H2,但Derby不理解这样的SQL语句。它抱怨第二个星号java.sql.SQLSyntaxErrorException:语法错误:在第1行第43列遇到*。您应该枚举所有列名,而不是*。“内部选择”在“外部选择”中是一个常量值,所以我认为它将被计算一次。但这取决于实现。是的,当我从表c、ID、VAR1中显式列出这样的列时,它也适用于Derby DB。所以我测试了这种方法,它看起来很有趣。它拓宽了我的SQL知识面。但它并不是更快。我对200K行4列的测试。显示对于嵌入式数据库,2次连续读取比组合选择快。在德比的情况下,我节省了15%的时间~109ms。在H2的情况下,我节省了35%的时间652ms。对于更快的连续读取版本,Derby的总读取时间为777ms,H2数据库的总读取时间为1839ms。5次测量的平均值