JDBC ResultSet с MySQL игнорирует тип ResultSet - PullRequest
0 голосов
/ 08 мая 2018

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

На официальном сайте 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);

Итак, я хотел бы спросить:

  1. Почему мой ResultSet всегда TYPE_FORWARD_ONLY?
  2. Есть ли способ изменить это поведение?

1 Ответ

0 голосов
/ 08 мая 2018

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 не поддерживает курсоры SQL, а драйвер JDBC не поддерживает подражать им, поэтому setCursorName () не имеет никакого эффекта.

Новые версии MySQL частично поддерживают курсоры (http://www.mysqltutorial.org/mysql-cursor/), но они по-прежнему не прокручиваются.

Итак, чтобы сделать то, что вы хотите, просто кэшируйте набор результатов (например, сохраните его в хэш-карте или в другом контейнере) и извлекайте конкретную запись, когда вам это нужно.

...