插入BLOB失败,文件为NULL

时间:2014-06-17 16:22:56

标签: java oracle jdbc blob

在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())));

它的工作原理不知何故不喜欢我的文件流。

关闭流是否有问题?这就是他们在我看到的所有样品上的表现。

2 个答案:

答案 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驱动程序将流的消耗推迟到实际执行。

另请注意,您与固定字符串的测试比较并不完全公平:它不是相同的方法重载,因此可能是一个工作而另一个不工作(尽管那个不是这里的情况。)