Oracle 的Blob使用小结

本文介绍Oracle数据库中Blob类型的两种读取方法及注意事项,包括使用PreparedStatement的getBinaryStream方法和getBlob方法。此外,还提供了使用Spring框架处理Blob的示例代码,并解决了处理大文件时流异常关闭的问题。
摘要由CSDN通过智能技术生成

Oracle 的Blob

Oracle的Lobs的流处理方式与Long等对象的Stream方式不一样,没有Long的诸多限制;只要保持连接,就能通过blob对象正确读取对象。
有两种方式可以读取Blob:
1.直接使用ps.getBinaryStream()的方法得到流对象
2.使用getBlob得到blob,然后通过blob的方法提供的getBinaryStream(),getBytes() 访问blob的数据。
这两种方法都可以在rs.close之后正确获取数据。(在spring 的JdbcTemplet环境下,该rs理论上被JdbcTemplet自动关闭;从数据库连接来看,连接也正确关闭了)。

使用Blob的好处是,按需获取Blob对象。而且可以多次通过blob.getBinaryStream得到对象。且Blob返回的对象可以使用mark/reset方法反复访问。且连接状态正常。
使用blob得到InputStream,可以调用close()接口,也可以不调用该接口,在连接关闭时将自动关闭该连接。最好调用close()释放资源。

c3p0的setBlob(pos,InputStream)接口不能正常工作。

写入或更新Blob时,可以使用ps.setBinaryStream();调用此接口后,in对象到文件尾(在把stream写入blob后,不能要再调用in.close()关闭文件,否则报错)。
也可以使用setBlob(pos,Blob)方法来写入或更新Blob字段;但是注意的是,无论是以blob还是blob.getBinaryStream的方式,都不能自己更新自己,否则死锁。

使用spring读取blob的示例程序:
            String sql = "select photo from my_photoes where id='test2' and photo is not null and rownum<2 ";
BLOB blob= (BLOB) simpleDao.queryForObject(sql,Blob.class);       
InputStream in = blob.getBinaryStream();
String filename = "./test/dao/pic" + 1+ ".gif";
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(filename));

            /* 需oracle的BLOB支持。效率可能会高些,但是空间上会有些浪费
byte[] b = new byte[blob.getBufferSize()];                //blob必须为oracle.sql.BLOB时才可调getBufferSize方法; 与java.sql.Blob区别。
System.out.println("bufferSize="+b.length);            //32k左右,用这种方式读取文件会有一点空间的浪费。
int len=-1;
while ((len = in.read(b)) != -1) {
out.write(b);
}
            */

            /*   纯jdbc方法:
                nt b;
     while ((b = in.read()) != -1) {
    out.write(b);
     }
            */

in.close();
out.close();


BLOB处理遇到的问题:
1.用spring的模板类来处理blob时,遇到大文件时,流会异常关闭。解决办法,使用oracle的本地连接来获取blob流,如下:
    public boolean queryForBlobStream(String sql,OutputStream fout)
    {
        boolean flag=true;
        try {
            Connection conn = DataSourceUtils.getConnection(getJdbcTemplate().getDataSource());
            conn.setAutoCommit(false);                         //此部分ms能提高性能
            Statement st = conn.createStatement();
            ResultSet rs = st.executeQuery(sql);
            if (rs.next()) {
                java.sql.Blob blob = rs.getBlob(1);
                InputStream ins = blob.getBinaryStream();
                //输出到文件
                //下面将BLOB数据写入文件
                byte[] b = new byte[1024];
                int len = 0;
                while ((len = ins.read(b)) != -1) {
                    fout.write(b, 0, len);
                }
                //依次关闭
                fout.close();
                ins.close();
            }
            conn.commit();
            rs.close();             //maybe not nessesary
            st.close();             //maybe not nessesary
            conn.close();
        } catch (IOException ex) {
            flag=false;
        } catch (SQLException ex) {
            flag=false;
        }
        return flag;
    }
2.如果把blob对象放到记录的字段中,在web开发中,通过blob.getBinaryStream()只能获得一次blob流,第二次调用同一对象的blob流会得到null流。
且在这种方式下,不能使用in.close()关闭流。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值