有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java何时可以安全地关闭PreparedStatement使用的InputStream。挫折?

PreparedStatement.setBlobPreparedStatement.setBinaryStream和其他一些PreparedStatement方法可以从InputStream中读取查询数据。不幸的是,读取数据时,上的文档根本不清楚。它只说

data will be read from the stream as needed until end-of-file is reached.

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

  • 在调用setBlob(或具有InputStream参数的其他方法)返回之前
  • 执行语句时
  • 当事务提交时

那么,在什么时候关闭InputStream(或所讨论的InputStream所依赖的其他资源)是安全的呢?它是否取决于驱动程序(我目前正在使用MySQL,但由于我喜欢保留迁移的可能性,因此了解其他驱动程序如何处理这一点也很好)


共 (1) 个答案

  1. # 1 楼答案

    写了一个快速的例子,用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()(在执行实际执行的hood方法下),但是在executeUpdate()完成后,流对象看起来是空闲的

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