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 。 
發佈了6 篇原創文章 · 獲贊 0 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章