PreparedStatement.setBlob
、PreparedStatement.setBinaryStream
和少数其他 PreparedStatement
方法可以从 中读取查询数据输入流
。不幸的是,文档对何时读取数据一点也不清楚。它只是说
data will be read from the stream as needed until end-of-file is reached.
对于何时需要数据,我可以想到三种可能的解释:
- 在调用 setBlob(或其他具有
InputStream
参数的方法)返回之前 - 语句执行时
- 事务提交时
那么,在什么时候关闭 InputStream
(或相关 InputStream
所依赖的其他资源)是安全的?它是否取决于驱动程序(我目前正在使用 MySQL
,但由于我希望保持开放的迁移可能性,因此了解其他驱动程序如何处理它可能也很好)?
最佳答案
写了一个简单的例子来在本地用 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 规范的驱动程序中都是一致的。那里可能有一些异常(exception),但如果它们支持 InputStream
,它应该以相同的方式工作。
关于java - 什么时候关闭 PreparedStatement.setBlob 使用的 InputStream 是安全的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21360131/