Вставка BLOB завершается неудачно, файл имеет значение NULL

1

В Java с JDBC я пытаюсь вставить файл в столбец BLOB в таблицу базы данных Oracle.

Вот как я продолжаю:

private Statement getStatement(File f, String fid, Long dex, String uid, int id)
{
  FileInputStream fis = null;
  PreparedStatement statement;
  try
  {
    statement = connection.prepareStatement("INSERT INTO BLOBTABLE (FID, FDEX, SFILE, UID, ID) VALUES (?, ?, ?, ?, ?)");
    statement.setString(1, fid);
    statement.setLong(2, dex);
    fis = new FileInputStream(file);
    statement.setBinaryStream(3, fis, file.length());
    statement.setString(4, uid);
    statement.setInt(5, id);
  }
  finally
  {
    if (fis != null)
      fis.close();
  }
  return statement;
}

private insertStuff()
{
  File f = new File("/home/user/thisFileExists");
  PreparedStatement statement = getStatement(f, "XYZ", 18L, "ABC", 78);
  statement.execute();
}

Когда выполняется.execute, я получаю ошибку Oracle:

java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("ORACLEUSER"."BLOBTABLE"."SFILE")

SFILE - столбец BLOB. Таким образом, это означает, что база данных в конце цепочки получает NULL в запросе.

Как так?

Если я заменю:

statement.setBinaryStream(3, fis, file.length());

С:

statement.setBinaryStream(3, new ByteArrayInputStream(("RANDOMSTRING".getBytes())));

Он работает так, что ему как-то не нравится мой файловый поток.

Проблема в том, что я закрываю поток? так они делают это на всех образцах, которые я видел.

  • 0
    Вставить '' пустую строку вместо null в случае BLOB столбца типа.
  • 0
    Помимо всего прочего - нет необходимости в «условии Йоды» для if (null != stream) . Просто используйте if (stream != null) , который большинство людей сочтет более читабельным.
Теги:
jdbc
blob

2 ответа

2

Вы закрываете FileInputStream перед выполнением инструкции, поэтому нет никакого способа, чтобы оператор мог получить данные, когда он действительно нуждается в этом. Лучше передать InputStream в ваш метод, чтобы вы могли закрыть его извне после выполнения оператора:

private insertStuff() {
    File file = new File("/home/user/thisFileExists");
    try (InputStream stream = new FileInputStream(file)) {
        PreparedStatement statement = getStatement(stream, "XYZ", 18L, "ABC", 78);
        statement.execute();
    }
}

... где getStatement будет принимать InputStream вместо File и использовать перегрузку setBinaryStream которая не принимает длину данных. Кроме того, вы можете передать File и он может открыть поток, создать инструкцию, выполнить инструкцию, а затем закрыть поток.

В качестве дополнительной заметки вы должны закрыть выражение, используя команду try-with-resource или try/finally.

  • 0
    Передавать длину на самом деле не нужно: достаточно просто передать поток, если вместо этого использовать setBinaryStream(int, InputStream)
  • 0
    @MarkRotteveel: Спасибо, редактирую.
Показать ещё 3 комментария
0

Вы закрываете FileInputStream до того, как база данных его использовала. Драйверу JDBC разрешено откладывать потребление потока до фактического выполнения.

Также обратите внимание, что ваше тестовое сравнение с фиксированной строкой не совсем справедливо: это не тот же метод перегрузки, поэтому может быть, что он работает, а другой - нет (хотя это не так).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню