Закрытие потокового набора результатов (с использованием mysql jdbc) занимает много времени
Я использую следующий код для создания подготовленного оператора и набора результатов потоковой передачи. Оказывается, что в некоторых случаях набор результатов довольно велик, но я хотел бы закрыть его после использования нескольких тысяч строк. Тем не менее, похоже, что close выполняется для всех оставшихся результатов - см. Эту ссылку для определения close: http://love.isti.com/libs/MySQL/com/mysql/jdbc/RowDataDynamic.java
statement = db.conn().prepareStatement(query, java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
db.setFetchSize(statement, kFetchSize);
Я хотел бы немедленно закрыть набор результатов (и / или оператор), не просматривая все оставшиеся результаты. Это возможно?
Я также пытался переместить курсор в конец набора результатов (afterLast), но это не поддерживается для потоковых наборов результатов. И не использовать потоковые наборы результатов не вариант, так как наборы результатов могут иногда быть очень большими, и я не хочу передавать все результаты клиенту.
Спасибо
1 ответ
Итак, как написано в моем комментарии к этому вопросу, официальный ответ от коннектора MySQL заключается в том, что для его закрытия необходимо передать весь набор результатов ( http://dev.mysql.com/doc/refman/5.5/en/connector-j-reference-implementation-notes.html). Кроме того, вы не можете выполнять больше запросов во время потокового результата.
Как отвратительный хакер, я использовал рефлексию, чтобы перейти в RowDataDynamic (версия 5.1.24) и подделать прерванное исключение, например так:
final Class<?> rdClass = rd.getClass();
final Field isInterruptedField = rdClass.getDeclaredField("isInterrupted");
isInterruptedField.setAccessible(true); // override 'protected' visibility
isInterruptedField.set(rd, true);
Обратите внимание, что вам придется пройтись по любому объекту, с которым у вас есть дескриптор, чтобы попасть в ResultSet. Для меня я использовал класс ScrollableResults Hibernate. Это означало получение ссылки ResultSet от него (на самом деле его суперкласса), а затем оттуда на RowData.
Это позволит выполнить операцию закрытия без потоковой передачи остальных результатов. ОДНАКО я получаю исключение из-за несоответствующего размера пакета при попытке отката транзакции (которую я просто ловлю и игнорирую). Используя Atomikos в качестве пула соединений, я буду видеть предупреждения о следующих нескольких соединениях, когда все будет очищено, но все по-прежнему работает нормально.
Очевидно, что этот подход может работать не для всех, но, по крайней мере, это обходной путь, когда обработка через запрос к базе данных или написание более сложной логики для получения результатов в пакетах просто не будет работать.