blob、clob字段小结(-)

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

/
// 图纸
/
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数据库中进行实际的存储


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 。

你可能感兴趣的:(数据库相关)