Blob,Clob字段

这种大容量字段有何用,也许大部分人马上联想到用来存储图片、文章,不过俺确是用它来存储Java串行化对象,当时用Swing做了个绘图工具,为了数据集中管理决定把图纸内容存到数据库,大家可以想象如果不用blob类型的字段,那表该如何设计呢?图元的种类N多,每个种类的属性N多,而且种类和属性都会变化,再加上还有图层的关系,最重要的一点就是存储速度(这个问题稍候我会解释)问题,要想设计出能完美解决以上问题的表结构将是想当困难的事,在项目进度的压力下对于两年前刚刚摆脱强大然而设计模式恶心的MFC,正投奔Java正营,边学语言边“设计”绘图工具的我,唯一能想到的而且最终证明在项目中成功实施的就是blob 字段了,当然blob字段不是万能药,所有信息都存在blob中将导致你的数据无法利用SQL的查询、过滤、统计等功能,所以对应重要的字段还是有必要把他们“拉”出来的,看看以下的表结构,你就明白了:
Sql代码
  1. /   
  2. // 图纸   
  3. /   
  4. create table EMHOOKUP   
  5. (   
  6.   PICID       NUMBER(8) not null,   
  7.   PICNAME     VARCHAR2(100) not null,   
  8.   PICTUREDATA BLOB,   
  9.   PICTYPE     NUMBER(8),   
  10.   PICMODIFYID NUMBER(8)   
  11. )   
  12. alter table EMHOOKUP add primary key (PICID)  
/
// 图纸
/
create table EMHOOKUP
(
  PICID       NUMBER(8) not null,
  PICNAME     VARCHAR2(100) not null,
  PICTUREDATA BLOB,
  PICTYPE     NUMBER(8),
  PICMODIFYID NUMBER(8)
)
alter table EMHOOKUP add primary key (PICID)


下面让我们来研究一下,如果在Oracle数据库中进行实际的存储

Java代码
  1. DBTemplate db = new DBTemplate() {   
  2.     public void dbProcess(Connection con) throws Exception {   
  3.         StringBuffer sql = new StringBuffer();   
  4.         sql.append(" insert into emhookup ");   
  5.         sql.append(" (picid, picname, picmodifyid, picturedata, pictype)values ");   
  6.         sql.append(" (?, ?, picmodifyidseq.nextval, EMPTY_BLOB(), ?)");   
  7.   
  8.         PreparedStatement ps = con.prepareStatement(sql.toString());   
  9.         ps.setInt(1, picID);   
  10.         ps.setString(2, picName);   
  11.         ps.setInt(3, data.picType);   
  12.         ps.executeUpdate();   
  13.         ps.close();   
  14.   
  15.         sql.setLength(0);   
  16.         sql.append(" select picturedata from emhookup ");   
  17.         sql.append(" where picid=? for update ");   
  18.         ps = con.prepareStatement(sql.toString());   
  19.         ps.setInt(1, picID);   
  20.         ResultSet rs = ps.executeQuery();   
  21.         if (rs.next()) {   
  22.             oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("picturedata");   
  23.             ObjectOutputStream out = new ObjectOutputStream(blob.getBinaryOutputStream());   
  24.             out.writeObject(DataProcess.toByteByGZIP(data));   
  25.             out.flush();   
  26.             out.close();   
  27.         }   
  28.         rs.close();   
  29.         ps.close();   
  30.     }   
  31. };   
  32. db.runWithTransaction();   
        DBTemplate db = new DBTemplate() {
            public void dbProcess(Connection con) throws Exception {
                StringBuffer sql = new StringBuffer();
                sql.append(" insert into emhookup ");
                sql.append(" (picid, picname, picmodifyid, picturedata, pictype)values ");
                sql.append(" (?, ?, picmodifyidseq.nextval, EMPTY_BLOB(), ?)");

                PreparedStatement ps = con.prepareStatement(sql.toString());
                ps.setInt(1, picID);
                ps.setString(2, picName);
                ps.setInt(3, data.picType);
                ps.executeUpdate();
                ps.close();

                sql.setLength(0);
                sql.append(" select picturedata from emhookup ");
                sql.append(" where picid=? for update ");
                ps = con.prepareStatement(sql.toString());
                ps.setInt(1, picID);
                ResultSet rs = ps.executeQuery();
                if (rs.next()) {
                    oracle.sql.BLOB blob = (oracle.sql.BLOB) rs.getBlob("picturedata");
                    ObjectOutputStream out = new ObjectOutputStream(blob.getBinaryOutputStream());
                    out.writeObject(DataProcess.toByteByGZIP(data));
                    out.flush();
                    out.close();
                }
                rs.close();
                ps.close();
            }
        };
        db.runWithTransaction(); 


从以上代码可知oracle中的blob/clob都需要先插入空数据empty_blob()/empty_clob()然后再锁定该行 for update 进行更新,并且必须在事务中运行runWithTransaction 。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值