开发者社区> 问答> 正文

jdbc读取blob类型内存问题:报错

Connection con = ConnectionFactory.getConnection();
 con.setAutoCommit(false);
 Statement st = con.createStatement();
 ResultSet rs = st.executeQuery("select contents from  BLOBIMG  where  id=1");
    if (rs.next()) {
        java.sql.Blob blob = rs.getBlob(1);
    在这里BLOB还是是在数据库的内存里吗?还是在本地java的对象里?
        InputStream ins = blob.getBinaryStream();
    在这读流的时候会不会重新检索数据库?是读取ResultSet里面结果?
    如果读取ResultSet里面的时候数据库里面的数据已经变了怎么去最新的啊
    求各位大神帮解答下谢谢诶

展开
收起
kun坤 2020-06-07 20:12:06 876 0
1 条回答
写回答
取消 提交回答
  • Hi,我看到了这样的一句话(来自ApiDoc),如下,  it returns false  when there are no more rows in the ResultSet  object, 也就是说他自己内部有一组行,所以你查询出来的结果应该全部在这里面,而不是先去索引。 java.sql.Blob blob = rs.getBlob(1); ,这一句我觉得可能传递的数据就是ResultSet内部的数据,这里应该是一个指针。如果数据库的数据已经改变了,那么应该重新读取一遍吧,ResultSet内部的数据才会改变。但是不排除会有一种sql的触发机制去触发ResultSet,但是你想想,这个需要回调,如果sql内部拥有一个回调的话就需要保留ResultSet地址,这样做是不明智的,所以sql拥有触发机制的可能性比较小,你应该做的就是去重新读取并生成新的ResultSet对象。最好的方法是去看ResultSet源代码,以上是我的推测,应该八九不离十。弱弱地问一句,你知道咋去看java源代码嘛?######下载个jd-gui反编译就能看代码了。我就想ResultSet自己重新读取DB######不过,这个设置是否会生效,得看驱动的具体实现,比如mysql的老驱动(3.0)完全不管这个,都是一次性全加载,是有堆溢出的风险的。######这个不一定是全部加载到内存,connection和statement有一个方法叫做setFetchSize,用来设置一个游标宽度,调用next的时候,会一次性取指定的结果条数到内存里面来,后面的next就单纯在内存里面操作,等内存里面的遍历完再取。而不是一次性全部到内存的。######

    Oracle的驱动包应该不好找源代码。暂时手边没有oracle也没法给你测试,说一下测试方法。

    建议用截包工具测试一下便知。如果读取流的时候仍然有从数据库读出数据,就证明至少不是一次性全部放在应用程序内存的。至于第二个问题,可以用JOptionPane.showMessageDialog弹一个对话框阻断当前线程之后,你手工修改数据库来测试。

    因为数据库连接是走网络通信,估计Blob的io流还是有buffered流的性质,具体这个要看具体的JDBC-Driver来实现

    ######InputStream ins = blob.getBinaryStream();之前将网线拔了,就会出现sql连接异常。可以证明是重新去链接DB取流了 。现在问题是如果我此时把数据库内数据改了,可是取出来的还是旧的数据,猜测肯能这个流是从ResultSe里取出的。我现在想ResultSet能及时反映数据库的内容
    2020-06-07 20:12:11
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
内存取证与IaaS云平台恶意行 为的安全监控 立即下载
云服务器ECS内存增强型实例re6全新发布 立即下载
低代码开发师(初级)实战教程 立即下载