Поддержка типов BLOB/CLOB в тонком клиенте JDBC#
Введение#
Начиная с версии DataGrid 17.0.0 появился доступ к новым возможностям работы с типами BLOB (Binary Large Object — двоичные большие объекты) и CLOB (Character Large Object — символьные большие объекты) в тонком клиенте JDBC.
В тонком клиенте JDBC доступны:
Базовая поддержка операций чтения, записи и модификации объектов данных типа BLOB/CLOB. Ранее поддержка типов BLOB/CLOB была доступна только для толстого клиента JDBC. Работа с BLOB/CLOB с помощью тонкого клиента характеризуется теми же особенностями функциональности и ограничениями по размеру данных, что и с помощью толстого клиента.
Поддержка Stream API для чтения и записи данных типов BLOB. В толстом клиенте JDBC поддержка Stream API для BLOB/CLOB отсутствует.
Особенности функциональности#
DataGrid — in-memory база данных, и ее решения оптимизированы для хранения данных в оперативной памяти (heap). Это ключевой аспект архитектуры DataGrid, который позволяет достигать высокой производительности за счет минимизации задержек доступа к данным.
Особенности функциональности для тонкого и толстого клиентов JDBC:
Глубокая оптимизация под BLOB/CLOB отсутствует — DataGrid хранит данные BLOB/CLOB внутри таблицы, что упрощает реализацию, но накладывает ограничение на размер передаваемых данных. Не рекомендуется использовать BLOB/CLOB больше нескольких МБ. Использование BLOB/CLOB невозможно для работы с информацией более 2 ГБ, так как будет превышен допустимый размер хранения в
byte[]и сгенерируется исключениеOutOfMemoryException.При использовании API по потоковой передаче данных DataGrid не обработает объекты данных типа BLOB частями (in chunks). Соответственно, это не приведет к уменьшению нагрузки на память, так как оптимизации под хранение объектов данных типа BLOB/CLOB нет.
Отсутствует поддержка Stream API для CLOB (например,
setCharacterStream()иsetAsciiStream()).Тонкий клиент JDBC не является потокобезопасным, поэтому следует избегать параллельного изменения данных.
После того, как экземпляр
JdbcClobилиJdbcBlobосвобожден с помощью методаfree(), любые дальнейшие попытки использовать этот экземпляр приведут к генерации исключенияSQLException.
В связи с этим для работы с объектами JdbcBlob и JdbcClob рекомендуется рассмотреть альтернативные методы:
Разделение больших файлов или данных на меньшие фрагменты (например, по 1 МБ каждый) и их хранение отдельными строками в таблице DataGrid.
Использование внешнего хранилища и сохранение только ссылки (например, пути к файлу, URL или уникального идентификатора) в таблице DataGrid.
Поддерживаемые операции#
Тип |
Функциональность |
Методы |
Описание |
|---|---|---|---|
CLOB |
Базовая поддержка для хранения и извлечения символьных данных |
|
Метод-конструктор. Параметр: |
|
Возвращает количество символов в значении CLOB, которое определено данным объектом CLOB |
||
|
Извлекает копию подстроки из значения CLOB, которая определена данным объектом CLOB. Подстрока начинается с позиции |
||
|
Возвращает значение CLOB, которое определено данным объектом CLOB, в виде объекта |
||
|
Возвращает объект |
||
|
Возвращает значение CLOB, которое обозначено данным объектом CLOB, как поток |
||
|
Находит позицию, на которой указанная подстрока |
||
|
Ищет положение, на котором строка |
||
|
Записывает указанную Java-строку в CLOB-значение, которое представляет данный объект CLOB, начиная с позиции Примечание: если значение |
||
|
Записывает Примечание: если значение |
||
|
Урезает значение CLOB, которое представляет данный объект CLOB, до длины Примечание: если указанное значение |
||
|
Метод освобождает ресурсы, которыми владеет объект CLOB. После вызова метода После вызова метода |
||
|
Метод считывает следующий байт данных из входного потока. Возвращаемое значение байта будет представлено целым числом в диапазоне от 0 до 255. Если байт недоступен, потому что достигнут конец потока, возвращается значение Этот метод должен реализовывать подкласс |
||
|
Метод Если поток находится в конце файла, возвращается значение Байты, которые были успешно прочитаны, сохраняются в массиве Метод |
||
|
Создает объект, который реализует интерфейс |
||
|
Устанавливает указанный параметр равным переданному объекту |
||
|
Возвращает значение указанного столбца в текущей строке данного объекта |
||
|
Возвращает значение указанного столбца в текущей строке данного объекта |
||
BLOB |
Базовая поддержка для хранения и извлечения бинарных данных |
|
Создает пустой объект данных типа BLOB. Предполагается, что этот метод будет вызван клиентом при создании объекта BLOB с помощью метода |
|
Создает объект данных типа BLOB, который оборачивает данные, хранящиеся в буфере Параметр: |
||
|
Создает объект данных типа BLOB, который оборачивает существующий массив байтов |
||
|
Возвращает количество байтов в значении BLOB, которые определены объектом данных типа BLOB |
||
|
Метод возвращает все или часть значений BLOB, которые представлены данным объектом BLOB, в виде массива байтов. Массив байтов состоит из |
||
|
Метод находит позицию байтового массива |
||
|
Метод определяет позицию байтового массива |
||
|
Метод записывает указанный массив байтов в значение BLOB, который управляется данным объектом BLOB, начиная с позиции Примечание: если значение |
||
|
Метод записывает указанные байты в значение BLOB, которое управляется данным объектом BLOB, начиная с позиции Примечание: если значение |
||
|
Метод Примечание: если значение |
||
|
Метод освобождает ресурсы, которые удерживает объект типа данных BLOB, и делает его недействительным. После вызова метода |
||
Поддержка потоков для данных типа BLOB |
|
Создает объект, который реализует интерфейс |
|
|
Возвращает значение указанного столбца в текущей строке данного объекта |
||
|
Возвращает значение указанного столбца в текущей строке данного объекта Данный метод также может использоваться для чтения абстрактных типов данных, специфичных для конкретной базы данных. В API JDBC 2.0 поведение метода Если метод |
||
|
Возвращает значение указанного столбца в текущей строке данного объекта Данный метод также может использоваться для чтения абстрактных типов данных, специфичных для конкретной базы данных. В API JDBC 2.0 поведение метода |
||
|
Метод Примечание: если значение |
||
|
Метод устанавливает параметр в объект Примечание: документация JDBC-драйвера может предоставить дополнительную информацию о том, как эффективнее передавать данные, если требуется выбор между передачей данных как LONGVARBINARY и как BLOB. Сверьтесь с документацией драйвера для выбора подходящего метода передачи данных |
||
|
Устанавливает указанный параметр в объект |
||
|
Возвращает значение указанного столбца в текущей строке данного объекта |
||
|
Возвращает значение указанного столбца в текущей строке данного объекта |
||
|
Устанавливает указанный параметр в заданный входной поток, у которого будет указанное количество байтов. Если нужно ввести очень большое двоичное значение в параметр типа LONGVARBINARY, может быть удобнее отправить его с помощью объекта Примечание: объект потока может быть стандартным объектом потока Java или пользовательским подклассом, который реализует стандартный интерфейс |
||
|
Устанавливает указанный параметр в заданный входной поток, у которого будет определенное количество байтов. Если нужно ввести очень большое двоичное значение в параметр типа LONGVARBINARY, может быть удобнее отправить его с помощью объекта Примечание: объект потока может быть стандартным объектом потока Java или пользовательским подклассом, который реализует стандартный интерфейс |
||
|
Устанавливает указанный параметр в заданный входной поток. Если нужно ввести очень большое двоичное значение в параметр типа LONGVARBINARY, может быть удобнее отправить его с помощью объекта Примечание: объект потока может быть стандартным объектом потока Java или пользовательским подклассом, который реализует стандартный интерфейс Примечание: ознакомьтесь с документацией JDBC-драйвера, чтобы определить, стоит ли использовать версию метода |
||
|
Извлекает значение указанного столбца в текущей строке данного объекта Примечание: все данные в возвращаемом потоке должны быть прочитаны перед получением значения любого другого столбца. Следующий вызов метода получения данных автоматически закрывает поток. Также поток может вернуть |
||
|
Извлекает значение указанного столбца в текущей строке данного объекта Примечание: все данные в возвращаемом потоке должны быть прочитаны перед получением значения любого другого столбца. Следующий вызов метода получения данных автоматически закрывает поток. Также поток может вернуть |
Примеры использования#
Работа с объектами JdbcBlob с использованием потока InputStream:
/** Запись объекта `JdbcBlob` с использованием потока `InputStream`. */
try (InputStream is = new FileInputStream("largefile.bin")) {
PreparedStatement stmt = conn.prepareStatement("INSERT INTO my_table (blob_column) VALUES (?)");
stmt.setBinaryStream(1, is);
stmt.executeUpdate();
}
/** Чтение объекта `JdbcBlob` с использованием потока `InputStream`. */
try (ResultSet rs = stmt.executeQuery("SELECT blob_column FROM my_table WHERE id = 1")) {
if (rs.next()) {
InputStream is = rs.getBinaryStream("blob_column");
// Обработка потока `InputStream`.
}
}
Используйте методы setClob() и getClob() для работы с CLOB. setClob() используется для передачи больших текстовых данных в базу данных, а метод getClob() — для получения этих данных из базы:
// Установка значения CLOB.
try (Connection conn = DriverManager.getConnection(url, user, password)) {
String clobData = "Большой текст...";
PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO my_table (clob_column) VALUES (?)"
);
pstmt.setClob(1, new StringReader(clobData));
pstmt.executeUpdate();
}
// Получение значения CLOB.
try (Connection conn = DriverManager.getConnection(url, user, password)) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT clob_column FROM my_table WHERE id = 1");
if (rs.next()) {
Reader reader = rs.getClob(1).getCharacterStream();
char[] buffer = new char[1024];
StringBuilder sb = new StringBuilder();
int charsRead;
while ((charsRead = reader.read(buffer)) > 0) {
sb.append(buffer, 0, charsRead);
}
System.out.println(sb.toString());
}
}
Используйте методы setBlob() и getBlob() для работы с BLOB. setBlob() используется для передачи больших бинарных данных в базу данных, а getBlob() — для получения этих данных из базы:
// Установка значения BLOB.
try (Connection conn = DriverManager.getConnection(url, user, password)) {
byte[] blobData = { /* Бинарные данные. */ };
PreparedStatement pstmt = conn.prepareStatement(
"INSERT INTO my_table (blob_column) VALUES (?)"
);
pstmt.setBlob(1, new ByteArrayInputStream(blobData));
pstmt.executeUpdate();
}
// Получение значения BLOB.
try (Connection conn = DriverManager.getConnection(url, user, password)) {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT blob_column FROM my_table WHERE id = 1");
if (rs.next()) {
Blob blob = rs.getBlob(1);
InputStream is = blob.getBinaryStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) > 0) {
// Обработка данных.
}
}
}