Кастомізація ResultSet
Сучасний JDBC API дозволяє дуже сильно кастомізувати об'єктиStatementіResultSet. Наприклад, за допомогоюResultSetможна змінювати рядки у базі даних.
При створенні об'єкта statement до нього можна передати купу наших побажань. Ці побажання можна поділити на три групи:
- Тип зв'язку з базою
- Управління одночасним доступом
- Збереженість та транзакції
Ці параметри можна надсилати під час створення об'єктаStatementабоПідпорядкованийдержавний. Приклад:
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. У разі проблем дивись офіційну документацію конкретної СУБД.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ