6.1 Знакомство с RowSet

Как ты уже знаешь, стандарту JDBC уже почти 20 лет, и он немного устарел. В него потихоньку добавляют новые типы и новые классы, но не везде это можно сделать красиво. И одно из таких мест — это ResultSet.

Работу с базой данных можно сделать более эффективной, но интерфейс ResultSet слабо для этого подходит. Кроме того, мы нигде явно не создаем его объекты, нам их возвращает метод executeQuery().

Создатели JDBC не стали долго думать и сделали механизм, полностью параллельный всему, что было до этого. И называться он стал RowSet.

Вот его основные преимущества:

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

Типы RowSet:

  • CachedRowSet
  • FilteredRowSet
  • JdbcRowSet
  • JoinRowSet
  • WebRowSet

6.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();

6.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);// Синхронизировать данные в базу данных

Если тебе интересно, как это работает, можешь ознакомиться с темой в официальной документации. Моя задача в настоящий момент — просто рассказать, что такое есть.