何时可以安全地关闭PreparedStatement.setBlob使用的InputStream?

时间:2014-01-26 05:34:16

标签: java mysql jdbc

PreparedStatement.setBlobPreparedStatement.setBinaryStream以及少数其他PreparedStatement方法可以从InputStream读取查询数据。不幸的是,当读取数据时,上的文档根本不清楚。它所说的全是

  

将根据需要从流中读取数据,直到文件结束为止   达到。

对于何时需要数据,我可以想到三种可能的解释:

  • 在调用setBlob(或其他具有InputStream参数的方法)之前返回
  • 执行声明时
  • 提交交易时

那么,在什么时候关闭InputStream(或者InputStream所涉及的其他资源)是否安全?它是否依赖于驱动程序(我目前正在使用MySQL,但由于我希望保持迁移的可能性,因此了解其他驱动程序如何处理它也可能很好?)

1 个答案:

答案 0 :(得分:2)

写了一个快速的例子来测试本地w / MySQL(原谅恶意异常处理):

public void testInputStream(String filePath) throws SQLException, IOException {
    DBUtil util = new DBUtil();//just a simple connection util
    Connection conn = util.getConnection("test");

    conn.setAutoCommit(false);

    File file = new File(filePath);
    FileInputStream fis = null;

    fis = new FileInputStream(file);

    String sql = "insert into testtable(scol,lob) values(?,?)";
    PreparedStatement stmt = conn.prepareStatement(sql);
    stmt.setString(1, "number4!");
    stmt.setBlob(2, fis);
    //fis.close() //this throws an exception
    stmt.executeUpdate();
    fis.close();//no exception here
    conn.commit();
    //fis.close();//no exception when called here
    stmt.close();
}

testtable是一个非常简单的表:

create table testtable (
    id int auto_increment primary key,
    scol varchar(50),
    lob blob
)engine=innodb;

执行语句后,似乎也是我测试中的正确答案。可能存在各种驱动程序不同的方式,但我认为在执行查询之前关闭InputStream的任何方案都不起作用。在浏览了MySQL PreparedStatement的源代码后,它看起来非常简单;它需要打开流来调用sendPacket()(在执行实际执行的引擎方法下)但在executeUpdate()完成后,流对象显示为空闲。

我认为你可以安全地假设这个行为在几乎任何实现JDBC规范的驱动程序中都是一致的。可能是一些例外,但如果它们支持InputStream,它应该以相同的方式工作。