Я пытаюсь запустить atomically
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();
Этот способ, похоже, работает. Я тестировал, что другой поток заблокирован для выполнения INSERT
между первым SELECT
и commit()
.
Это правильный и оптимальный способ? Могу ли я быть уверенным, что таким образом мой COUNT всегда будет таким же, как число строк, возвращаемое из следующего выбора?
Также я ожидал бы, что вместо Connection.TRANSACTION_SERIALIZABLE
будет Connection.TRANSACTION_REPEATABLE_READ
.
Но это не работает в Дерби 10.11.1.1. Это ошибка? Я новичок в бизнесе базы данных, но он работает как ожидается для базы данных H2 - поэтому я ожидаю, что это может быть ошибка в дерби...
Обратите внимание, что я уже знаю о решении, где вы можете:
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 раза медленнее.