В 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())));
Он работает так, что ему как-то не нравится мой файловый поток.
Проблема в том, что я закрываю поток? так они делают это на всех образцах, которые я видел.
Вы закрываете 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.
setBinaryStream(int, InputStream)
Вы закрываете FileInputStream
до того, как база данных его использовала. Драйверу JDBC разрешено откладывать потребление потока до фактического выполнения.
Также обратите внимание, что ваше тестовое сравнение с фиксированной строкой не совсем справедливо: это не тот же метод перегрузки, поэтому может быть, что он работает, а другой - нет (хотя это не так).
''
пустую строку вместоnull
в случаеBLOB
столбца типа.if (null != stream)
. Просто используйтеif (stream != null)
, который большинство людей сочтет более читабельным.