Кастомизация ResultSet
Современный JDBC API позволяет очень сильно кастомизировать объекты Statement и ResultSet. Например, с помощью ResultSet можно менять строки в базе данных.
При создании объекта statement в него можно передать кучу наших пожеланий. Эти пожелания можно разделить на три группы:
- Тип связи с базой
- Управление одновременным доступом
- Сохраняемость и транзакции
Эти параметры можно передавать при создании объекта Statement или PreparedStatement. Пример:
Statement statement = connection.createStatement(
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_OVER_COMMIT );
PreparedStatement statement = connection.prepareStatement(sql,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY,
ResultSet.CLOSE_CURSORS_OVER_COMMIT);
Глубоко эти вещи мы изучать не будем, но я хочу, чтобы ты знал, что такое возможно, если встретишь что-то похожее в чужом коде.
Типы ResultSet
ResultSet может быть определенного типа. Тип определяет некоторые характеристики и возможности ResultSet.
Не все типы поддерживаются всеми базами данных и драйверами JDBC. Тебе придется проверить свою базу данных и драйвер JDBC, чтобы увидеть, поддерживает ли он тип, который ты хочешь использовать. Метод DatabaseMetaData.supportsResultSetType(int type) возвращает true или false в зависимости от того, поддерживается данный тип или нет.
На момент написания статьи существует три типа ResultSet:
- ResultSet.TYPE_FORWARD_ONLY
- ResultSet.TYPE_SCROLL_INSENSITIVE
- ResultSet.TYPE_SCROLL_SENSITIVE
Тип по умолчанию — TYPE_FORWARD_ONLY.
TYPE_FORWARD_ONLY означает, что ResultSet можно перемещать только вперед. То есть ты можешь перемещаться только из строки 1, строки 2, строки 3 и т. д. В ResultSet ты не можешь двигаться назад: нельзя считать данные из 9-й строки после чтения десятой.
TYPE_SCROLL_INSENSITIVE означает, что ResultSet можно перемещать (прокручивать) как вперед, так и назад. Ты также можешь перейти к позиции относительно текущей позиции или перейти к абсолютной позиции.
ResultSet этого типа нечувствителен к изменениям в базовом источнике данных, пока ResultSet открыт. То есть если запись в ResultSet изменяется в базе данных другим потоком или процессом, она не будет отражена в уже открытых ResultSet этого типа.
TYPE_SCROLL_SENSITIVE означает, что ResultSet можно перемещать (прокручивать) как вперед, так и назад. Ты также можешь перейти к позиции относительно текущей позиции или перейти к абсолютной позиции.
ResultSet этого типа чувствителен к изменениям в базовом источнике данных, пока ResultSet открыт. То есть если запись в ResultSet изменяется в базе данных другим потоком или процессом, она будет отражена в уже открытых ResultSet этого типа.
Concurrency
Параллельность ResultSet определяет, может ли ResultSet обновляться, или только считываться.
Некоторые базы данных и драйверы JDBC поддерживают обновление ResultSet, но не все. Метод DatabaseMetaData.supportsResultSetConcurrency(int concurrency) возвращает значение true или false в зависимости от того, поддерживается данный режим параллелизма или нет.
ResultSet может иметь один из двух уровней параллелизма:
- ResultSet.CONCUR_READ_ONLY
- ResultSet.CONCUR_UPDATABLE
CONCUR_READ_ONLY означает, что ResultSet может быть только прочитан.
CONCUR_UPDATABLE означает, что ResultSet может быть прочитан и изменен.
Пример изменения данных в базе
С помощью этих параметров ты можешь управлять создаваемым Statement и его ResultSet.
Например, можно создать обновляемый ResultSet и с его помощью менять базу данных. При создании Statement важно соблюсти следующие условия:
- указывается только одна таблица
- не содержит предложений join или group by
- столбцы запроса должны содержать первичный ключ
При выполнении вышеуказанных условий обновляемый ResultSet может быть использован для модификации таблицы в базе данных. При создании объекта Statement нужно указать такие параметры:
Statement st = createStatement(Result.TYPE_SCROLL_INSENSITIVE, Result.CONCUR_UPDATABLE)
Результатом выполнения такого оператора является обновляемый набор результатов. Метод обновления заключается в перемещении курсора ResultSet в строку, которую ты хочешь обновить, а затем в вызове метода updateXXX().
Метод updateXXX работает аналогично методу getXXX(). Метод updateXXX() имеет два параметра. Первый — это номер обновляемого столбца, который может быть именем столбца или серийным номером. Второй — это данные, которые необходимо обновить, и этот тип данных должен быть тот же, что и XXX.
Чтобы строка реально обновилась в базе, нужно вызвать метод updateRow() до того, как курсор ResultSet покинет измененную строку, в противном случае изменения так и не попадут в базу.
Также можно добавлять новые строки в таблицу:
Сначала нужно переместить курсор на пустую строку. Для этого нужно вызвать метод moveToInsertRow().
Затем нужно заполнить эту строку данными с помощью метода updateXXX().
Затем нужно вызвать метод inserRow(), чтобы строка добавилась в базу.
Ну и наконец нужно вернуть курсор обратно, вызвав метод moveToCurrentRow().
Важно! Не все СУБД поддерживают данные параметры для расширенного оператора Statement. В случае наличия проблем смотри официальную документацию конкретной СУБД.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ