使用Derby读取大数据(BLOB、CLOB)的问题

来源:互联网 发布:mac android 文件传输 编辑:程序博客网 时间:2024/04/24 07:43
最近在项目中使用derby读取BLOB时出现了一个错误:
java.io.IOException: ERROR 40XD0: Container has been closed.
at org.apache.derby.impl.store.raw.data.OverflowInputStream.fillByteHolder(Unknown Source)
at org.apache.derby.impl.store.raw.data.BufferedByteHolderInputStream.available(Unknown Source)
at java.io.FilterInputStream.available(Unknown Source)
at java.io.FilterInputStream.available(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at java.io.FilterInputStream.read(Unknown Source)
at java.io.PushbackInputStream.read(Unknown Source)

在网上google一下,发现在derby中读取大数据时,如果同一个connection中还有其他的Statement或ResultSet,而且connection是自动提交的,那么就可能导致大数据无法全部读出来,如下面的示例:

public InputStream getData() {
    Connection con = null;
    Statement stmt = null;
    ResultSet rs = null;
    Statement stmt2 = null;
    ResultSet rs2 = null;
    try {
         stmt...
         rs...
         stmt2...
         return MyInputStream(con, stmt2, rs2);
    } finally {
        rs.close();
        stmt.close();        
    }
}
    也许上面的代码并不被建议使用,但是有的时候是迫不得已的。
    这样的代码在读取小数据量的BLOB的时候也许可以运行,但是如果读取的BLOB比较大,那么读到一半的时候就有可能出现上面给出的错误,其实原因就在于finally中将另外的Statement和ResultSet关闭了,这是就会导致一个事务的提交,从而导致获取大数据的流也关闭,不知道这样是不是合乎逻辑,不过在其他的数据库中似乎没有这样的问题。
    我的解决办法就是在stmt和rs结束之后,读取BLOB之前将其关闭,这样就不会有事务被提交了。当然还有另外一个解决办法,就是调用connection.setAutoCommit(false),但是这样的调用对使用了连接池的应用有隐患,一旦在方法结束后如果没有调用connection.setAutoCommit(true),那么导致非常严重的问题,所以我就没有采用这样的方法!
原创粉丝点击