Закрытие потокового набора результатов (с использованием 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 в качестве пула соединений, я буду видеть предупреждения о следующих нескольких соединениях, когда все будет очищено, но все по-прежнему работает нормально.

Очевидно, что этот подход может работать не для всех, но, по крайней мере, это обходной путь, когда обработка через запрос к базе данных или написание более сложной логики для получения результатов в пакетах просто не будет работать.

Другие вопросы по тегам