在Java中,使用JDBC我试图在Oracle数据库的表中的BLOB列中插入文件。
以下是我的工作方式:
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 :(得分: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语句关闭语句。
答案 1 :(得分:0)
您在数据库使用它之前关闭FileInputStream
。允许JDBC驱动程序将流的消耗推迟到实际执行。
另请注意,您与固定字符串的测试比较并不完全公平:它不是相同的方法重载,因此可能是一个工作而另一个不工作(尽管那个不是这里的情况。)