Я пытаюсь обработать большой объем данных в приложении Java. Данные хранятся в базе данных MySQL, и я использую соединитель jdbc 8.0.11.
Моя проблема в том, что мне нужно обращаться к каждой записи несколько раз, а повторное выполнение запроса занимает слишком много времени. Использование ResultSet.absolute(1) вызывает исключение, объясняющее, что курсор - TYPE_FORWARD_ONLY.
Как описано здесь, оператор должен быть создан с параметрами ResultSet.TYPE_SCROLL_INSENSITIVE и параметром ResultSet.CONCUR_READ_ONLY, чтобы получить набор результатов с возможностью прокрутки.
Но мой созданный ResultSet всегда является ResultSet.TYPE_FORWARD_ONLY, игнорируя любые параметры, предоставленные в методе оператора create.
В официальном Сайт MySQL я не нашел ни объяснений, ни информации, поддерживается ли эта функция.
Для тестового случая я написал этот код, чтобы проверить, не повлияет ли какая-либо другая комбинация на тип ResultSet, и всегда получал TYPE_FORWARD_ONLY.
Connection conn = Database.getConnection();
Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
if (st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
System.out.println("Should be scroll sensitive, is forward only");
}
st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
if (st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
System.out.println("Should be scroll insensitive, is forward only");
}
st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
if (st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
System.out.println("Should be scroll insensitive, is forward only");
}
st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
if (st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
System.out.println("Should be scroll sensitive, is forward only");
}
st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
if (st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
System.out.println("Should be scroll sensitive, is forward only");
}
st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE,ResultSet.HOLD_CURSORS_OVER_COMMIT);
if (st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
System.out.println("Should be scroll insensitive, is forward only");
}
st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY,ResultSet.HOLD_CURSORS_OVER_COMMIT);
if (st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
System.out.println("Should be scroll insensitive, is forward only");
}
st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE,ResultSet.HOLD_CURSORS_OVER_COMMIT);
if (st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
System.out.println("Should be scroll sensitive, is forward only");
}
st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY,ResultSet.HOLD_CURSORS_OVER_COMMIT);
if (st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
System.out.println("Should be scroll sensitive, is forward only");
}
Вот фрагмент кода, объясняющий, как я создаю соединение с базой данных:
private static final String driverName = "com.mysql.cj.jdbc.Driver";
com.mysql.cj.jdbc.Driver dr = (com.mysql.cj.jdbc.Driver) Class.forName(driverName).newInstance();
MysqlDataSource src = new MysqlDataSource();
src.setUseCursorFetch(true);
src.setServerName("localhost");
src.setPort(port);
src.setDatabaseName("dbname");
src.setUseSSL(false);
src.setUser(dbUser);
src.setPassword(dbPass);
src.setServerTimezone("GMT+2");
conn = src.getConnection(dbUser, dbPass);
Поэтому я хотел бы спросить:
ResultSet всегда TYPE_FORWARD_ONLY?



JDBC ResultSet семантически похож на курсор базы данных, но не все системы баз данных, включая MySQL, поддерживают курсоры (см. Ниже). Если реализованы TYPE_SCROLL_SENSITIVE или TYPE_SCROLL_INSENSITIVE, это обычно означает, что драйвер JDBC нацелен на базу данных, поддерживающую прокручиваемые курсоры. Конечно, драйвер JDBC все еще может быть написан для имитации этого поведения путем кэширования набора результатов, но большинство драйверов этого не делают.
Из документации MySQL ((src: https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-implementation-notes.html)
MySQL does not support SQL cursors, and the JDBC driver does not emulate them, so setCursorName() has no effect.
Новые версии MySQL частично поддерживают курсоры (http://www.mysqltutorial.org/mysql-cursor/), но они по-прежнему не прокручиваются.
Итак, чтобы делать то, что вы хотите, просто кешируйте набор результатов (например, сохраните его в хэш-карте или другом контейнере) и извлекайте конкретную запись, когда она вам нужна.
Драйверам JDBC разрешено понизить тип набора результатов, если они не могут выполнить запрос. Однако у меня создалось впечатление, что MySQL Connector / J действительно поддерживает (или, по крайней мере, моделирует) прокручиваемые курсоры. Интересно, изменили ли они это в версии 8.