BLOB-поля

BLOB-поля позволяют хранить в ячейке таблицы большие объёмы данных — например, целые файлы с документами. Работа с этими полями через курсор отличается от работы с полями других типов.

  1. Поля курсора, соответствующие BLOB-полям, имеют тип данных BLOB.

  2. Получить экземпляр класса BLOB и присвоить его полю курсора можно только одним способом: вызвав в курсоре метод calc<имя поля>(). Например, если BLOB-поле имеет название foo, то соответствующий метод курсора называется calcfoo(), и после его вызова будет заполнено соответствующее поле курсора.

  3. В отличие от полей других типов, которые автоматически заполняются данными таблицы при чтении записи методами get(), next() и т. п., BLOB-поля при выполнении этих методов не заполняются, а всегда получают значение null. Чтобы прочитать BLOB-поле, необходимо вызвать метод calc…​(). При этом, если курсор указывает на существующую в таблице запись, вызов метода calc…​() приведёт к чтению содержимого BLOB-а из базы данных в оперативную память. Поэтому calc…​() следует вызывать лишь тогда, когда есть намерение прочитать или изменить содержимое BLOB-а.

  4. После вызова метода calc<имя поля>(), соответствующее поле курсора инициализируется объектом с типом BLOB. Методы этого объекта позволяют читать и изменять его содержимое и описаны далее. После изменения содержимого объекта BLOB можно воспользоваться методом update() или insert().

  5. Если BLOB необходимо стереть из базы данных, записав в соответствующую ячейку значение NULL, нужно воспользоваться методом setNull() объекта BLOB, а затем вызвать update(). Присвоение полю значения null через сеттер, в отличие от полей других типов, не сработает, т. к. будет проинтерпретировано системой, как если бы BLOB не был прочитан из базы, и по update() ничего не изменится.

Методы класса BLOB:

getInStream()

возвращает экземпляр класса java.io.InputStream, из которого можно прочитать содержимое курсора или null, если в ячейке таблицы базы данных содержится значение NULL. Допускается многократный вызов этого метода, при этом всякий раз будет создаваться новый поток, читающий с начала.

getOutStream()

стирает все данные BLOB-а в памяти (если они были) и создаёт экземпляр java.io.OutputStream, в который можно записать данные для BLOB-а. Следует подчеркнуть, что каждый вызов getOutStream() удаляет из BLOB-а в памяти все данные, даже если в полученный поток ничего не будет записано. Также следует подчеркнуть, что этот метод меняет данные только в представлении BLOB в оперативной памяти, реальная запись в базу данных происходит только после вызова методов insert() или update() на курсоре.

setNull()

устанавливает для BLOB-а значение NULL.

isModified()

возвращает true, если первоначальные данные объекта были изменены вызовами getOutStream() или setNull().

size()

возвращает размер внутренних данных BLOB-а в байтах.

Примеры кода для работы с BLOB-полем:

OrderLineCursor line = new LineCursor(context);
//Далее подразумевается, что line.dat — BLOB-поле
. . .
//Пример записи
line.calcDat();
try(OutputStreamWriter osw = new OutputStreamWriter(
    line.getDat().getOutStream(), StandardCharsets.UTF_8)){
    osw.append("hello, blob field!");
}
. . .
//Пример чтения
line.calcDat();
InputStream ins = line.getDat().getInStream();
//Помним о том, что в поле может быть NULL
if (Objects.nonNull(ins)){
    try ( BufferedReader inr = new BufferedReader(
        new InputStreamReader(ins, StandardCharsets.UTF_8))) {
        //В консоль будет выведено содержимое BLOB-поля,
        //например, 'hello, blob field!'
                System.out.println(inr.readLine());
    }
}