JDBC перечитывает данные в ResultSet - PullRequest
2 голосов
/ 07 февраля 2012

Я получаю простой ResultSet из моей базы данных SQL Server, используя драйвер JDBC Microsoft (mssqlserver.jar).Я думаю, что это драйвер MSSQL2000, который загружается из [Microsoft JDBC] [1]

Я хочу вызывать методы получения более одного раза для доступа к значениям, но при этом выдается следующее исключение:

java.sql.SQLException: [Microsoft] [Драйвер SQLServer 2000 для JDBC] ResultSet не может перечитать данные строки для столбца 1.

Вопрос в том, что яизвлечение данных в ResultSet.Из ResultSet я обращаюсь к данным в своем коде перед передачей ResultSet в другое место в коде для повторного использования.

Код подобен следующему:

// build query string
String selectQuery = "SELECT * FROM SomeWhere";

// get the data
Statement statement = sourceConnection.createStatement();
ResultSet rs = statement.executeQuery(selectQuery);

while( rs.next() ) {

    // do my own internal processing 
    doSomethingWithRs(rs);

    // now do something with the record set outside - in subclass
    afterRowCopied(rs);
}

// ...

private void doSomethingWithRs(ResultSet rs) {
    // access data   
    for( int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
        Object o = rs.getObject(i);
        // do something with o...
    }

}

Редактировать

Я использую для этого Java 1.6.

end Редактировать

Есть мысли?Все, что я могу сделать, это переупаковать данные с ResultSetMetaData в пользовательский класс.

На самом деле не найдено слишком много сообщений по этой проблеме.Сайт Microsoft не помогает вообще.

Ответы [ 3 ]

2 голосов
/ 07 февраля 2012

Похоже, что это проектно, согласно Ошибка «ResultSet не может перечитать данные строки» »при чтении данных из объекта ResultSet JDBC :

Эта ошибкапроисходит с объектами ResultSet, которые содержат столбец BLOB (например, типы данных text, ntext или image).Драйвер не может вернуть столбец BLOB не по порядку, потому что он не кэширует все содержимое типов данных BLOB из-за ограничений размера.

Для любой строки в ResultSet вы можете прочитать любой столбец слева направо,и каждый столбец следует читать только один раз.Если вы попытаетесь прочитать столбцы не по порядку или перечитаете столбец из ResultSet, вы можете получить сообщение об ошибке, описанное в разделе «Проблема».

Такое поведение предусмотрено.

Вам нужно либо использовать другой драйвер JDBC, либо реорганизовать свой код, чтобы эти столбцы BLOB читались только один раз для любой данной строки.В любом случае, это хорошая идея, поскольку перечитывание BLOB-файлов может привести к снижению производительности.

1 голос
/ 07 февраля 2012

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

Редактировать

Как я уже говорил, я использую JDK 1.6. Однако при компиляции с использованием JDK 1.7 возникает ошибка компиляции:

error: ReadOnlyResultSet is not abstract and does not override abstract method <T>getObject(String,Class<T>) in ResultSet

конец Редактировать

Для этого создайте класс, который реализует ResultSet (пусть Netbeans добавляет заглушки реализации метода по умолчанию). Затем в конструкторе сохраните ссылку на исходный ResultSet. В next () кэшируйте значения в массиве. Вероятно, придется сделать то же самое для previous () и других методов установки курсора. Таким образом, класс будет выглядеть так:

public class ReadOnlyResultSet
    implements ResultSet {
    /**
     * The original data source.
     */
    private ResultSet source;
    /**
     * Cached values for the current row.
     */
    private Object[] values;

    /**
     * Creates a new instance of <code>ReadOnlyResultSet</code>.
     */
    public ReadOnlyResultSet(ResultSet source) {
        this.source = source;
    }

    @Override
    public boolean next() throws SQLException {
        // NOTE:  values[0] will always be null as JDBC is 1 based arrays
        boolean next = source.next();
        if( next ) {
            values = new Object[source.getMetaData().getColumnCount() + 1];
                for(int i = 1; i < source.getMetaData().getColumnCount(); i++ ) {
                    values[i] = source.getObject(i);
                }
            } else {
                // no current row
                values = new Object[] { };
            }

            return next;
        }

        // implement all of the not getter/setter methods
        @Override
        public void close() throws SQLException {
            source.close();
        }

        // implement getters I am interested in
        @Override
        public String getString(int columnIndex) throws SQLException {
            return (String) values[columnIndex];
        }

        @Override
        public String getString(String columnLabel) throws SQLException {
            return (String) values[findColumn(columnLabel)];
        }

        // just too much implementation but hopefully you get the drift

}

1 голос
/ 07 февраля 2012

Я бы предложил прочитать данные один раз и скопировать в массив Object и передать их в методы вместо передачи результирующего набора.Это может быть и более чистый код.

...