1. Знайомство з RowSet

Як ти вже знаєш, стандарту JDBC вже майже 20 років, і він трохи застарів. До нього потихеньку додають нові типи та нові класи, але не скрізь це можна зробити красиво. І одне з таких місць — це ResultSet.

Роботу з базою даних можна зробити більш ефективною, але інтерфейс ResultSet заледве для цього підходить. До того ж, ми ніде явно не створюємо його об'єкти: нам їх повертає метод executeQuery().

Творці JDBC не стали довго думати і зробили механізм, повністю паралельний до всього, що було до цього. І називатися він став RowSet.

Ось його основні переваги:

  • RowSet розширює інтерфейс ResultSet, тому його функції потужніші, ніж у ResultSet.
  • RowSet більш гнучко пересувається даними таблиці і може прокручувати назад та вперед.
  • RowSet підтримує кешовані дані, які можна використовувати навіть після закриття з'єднання.
  • RowSet підтримує новий спосіб підключення: ти можеш підключитися до бази даних без підключення. Також він підтримує читання джерела даних XML.
  • RowSet підтримує фільтр даних.
  • RowSet також підтримує операції з'єднання таблиць.

Типи RowSet:

  • CachedRowSet
  • FilteredRowSet
  • JdbcRowSet
  • JoinRowSet
  • WebRowSet

2. Створення об'єкта RowSet

Є три різні способи отримати робочий об'єкт.

По-перше, його можна заповнити даними з ResultSet, отриманого класичним способом.

Наприклад, ми можемо закешувати дані ResultSet за допомогою CachedRowSet:


Statement statement = connection.createStatement();
ResultSet results = statement.executeQuery("SELECT * FROM user");
 
RowSetFactory factory = RowSetProvider.newFactory();
CachedRowSet crs = factory.createCachedRowSet() ;
crs.populate(results); // Використовуємо ResultSet для заповнення

По-друге, можна зробити повністю автономний об'єкт RowSet, створивши для нього своє власне підключення до бази даних:


JdbcRowSet rowSet = RowSetProvider.newFactory().createJdbcRowSet();
rowSet.setUrl("jdbc:mysql://localhost:3306/test");
rowSet.setUsername("root");
rowSet.setPassword("secret");
 
rowSet.setCommand("SELECT * FROM user");
rowSet.execute();

І по-третє, можна підключити RowSet до вже наявного з'єднання:


 Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
JdbcRowSet rowSet = new JdbcRowSetImpl(con);
 
rowSet.setCommand("SELECT * FROM user");
rowSet.execute();

3. Приклади роботи з RowSet

Приклад перший: кешування.

Давай напишемо код, де за допомогою CachedRowSet закешуємо всі дані та читатимемо їх із вже закритого з'єднання:


Statement statement = connection.createStatement();
ResultSet results = statement.executeQuery("SELECT * FROM user");
 
RowSetFactory factory = RowSetProvider.newFactory();
CachedRowSet crs = factory.createCachedRowSet() ;
crs.populate(results); // Використовуємо ResultSet для заповнення
 
connection.close(); // Закриваємо з'єднання
 
// Дані з кешу все ще доступні
while(crs.next()) {
  System.out.println(crs.getString(1)+"\t"+ crs.getString( 2)+"\t"+ crs.getString(3));
}

Приклад другий: зміна рядків через RowSet:


 // Підключаємося до бази даних
 CachedRowSet crs = rsf.createCachedRowSet();
 crs.setUrl("jdbc:mysql://localhost/test");
 crs.setUsername("root");
 crs.setPassword("root");
 crs.setCommand("SELECT * FROM user");
 crs.execute();
 
// Цей тип операції може змінити лише автономний RowSet
// Спочатку пересуваємо покажчик на порожній (новий) рядок, поточна позиція запам'ятовується
 crs.moveToInsertRow();
 crs.updateString(1, Random.nextInt());
 crs.updateString(2, "Клон" + System.currentTimeMillis());
 crs.updateString(3, "Жіночий");
 crs.insertRow(); // Додаємо поточний (новий) рядок до інших рядків
 crs.moveToCurrentRow(); // Повертаємо покажчик на той рядок, де він був до вставлення
 
 crs.beforeFirst();
 while(crs.next()) {
 System.out.println(crs.getString(1) + "," + crs.getString(2) + "," + crs.getString(3));
}
 
// А тепер ми можемо всі наші зміни залити до бази
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/dbtest", "root", "root");
con.setAutoCommit(false); // Потрібно для синхронізації
crs.acceptChanges(con);// Синхронізувати дані до бази даних

Якщо тобі цікаво, як це працює, можеш ознайомитись із темою в офіційній документації. Моє завдання зараз просто розповісти, що таке є.