hibernate映射操作Blob文章(第1篇)

本文介绍了如何在Hibernate框架中处理Blob和Clob字段,并详细解释了在不同数据库(如SQL Server和Oracle)中对这些字段进行读写的步骤。同时对比了在两种数据库环境下处理Lob字段的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

blob字段采用单字节存储,适合保存二进制数据,如图片文件;Clob字段采用多字节存储,适合保存大型文本数据。

SQL Server中,Blob和Clob分别对应image和ntext

先在TUser表中新增两个字段image类型的image,ntext类型的resume

TUser.hbm.xml增加两个属性/字段映射

<property name="image" column="image" type="java.sql.Blob"/>

<property name="resume" column="resume" type="java.sql.Clob"/>

TUser.java增加两个域

private Blob image; private Clob resume;

OK, 可以这样来存

TUser user = new TUser();

user.setName("earth");

user.setImage(Hibernate.createBlob(new FileInputStream("C:\\myimage.jpg")));

user.setResume(Hibernate.createClob("This is a clob"));

session.save(user);

Hibernate为我们提供了一序列生成LOB字段的静态方法

public static Blob createBlob(byte[] bytes)

public static Blob createBlob(InputStream stream, int length)

public static Blob createBlob(InputStream stream)

public static Clob createClob(String string)

public static Clob createClob(Reader reader, int length)

对应的读取操作如下:

TUser user = (TUser)session.load(TUser.class, new Integer(id));

Blob image = resume.getImage();

// ---

InputStream is = image.getBinaryStream();

FileOutputStream fos = new FileOutputStream("C:\\outImg.jpg");

byte[] buf = new byte[102400];

int len;

while((len = is.read(buf)) != -1){

fos.write(buf,0,len);

}

fos.close();

is.close();

// --

Clob resume = user.getResume();

System.out.println(resume.getSubString(1,(int)resume.length()));

SQL ServerBlob, Clob的读写都非常简单Oracle相对复杂

Hibernate下修改数据库很简单hibernate.cfg.xml中切换一下Dialect,再次运行上面的代码

错误1:streams type cannot be used in batching.

解决<property name="hibernate.jdbc.batch_size">0</property>

错误2:Connnection reset by peer: socket write error.

解决:Oracle中的Blob/Clob字段本身拥有一个游标,JDBC必须通过游标对Lob字段进行操作,在Lob字段创建之前,我们无法获取其游标句柄,所以要先创建一个空的Lob字段以先获得操作Lob字段的句柄,晕!

在一般的JDBC中,对Oracle Lob字段的写分三步:

STEP 1: insert into(image,resume)values(?,?);

pstmt.setBlob(index,oracle.sql.BLOB.empty_lob())

pstmt.setClob(index,oracle.sql.CLOB.empty_lob())

pstmt.executeUpdate();

STEP2: select image,resusme from... for update

注意!!!必须加for update,这将锁定该行,直至该行被修改完毕,保证不产生并发冲突。

java.sql.ResultSet rs = pstmt.executeQuery();

weblogic.jdbc.vendor.oracle.OracleResultSet

//获得Lob字段的操作句柄

oracle.sql.BLOB image = (oracle.sql.BLOB)rs.getBlob(1);

oracle.sql.CLOB resume =(oracel.sql.CLOB)rs.getClob(2);

weblogic.jdbc.vendor.oracle.OracleThinBlob

weblogic.jdbc.vendor.oracle.OracleThinClob

//将文本写入Clob

resume.putString(1,"This is my clob");

//将图片写入Blob,不是直接对image操作而是先获得它的一个OutputStream

FileInputStream fis = new FileInputStream("C:\\inputImg.jpg");

OutputStream imageStream = image.getBinaryOutputStream();

byte[] buf = new byte[10240]; //10K缓存

int len;

while((len=fis.read(buf))>0){

imageStream.write(buf,0,len);

}

fis.close();

imageStream.close();

STEP3: update .. set image=?, resume=?

pstmt.setBlob(1,image);

pstmt.setClob(2,resume);

pstmt.executeUpdate();

Hibernate相应的实现过程如下

STEP 1:

TUser user = new TUser();

user.setName("Earth");

user.setImage(Hibernate.createBlob(new byte[1]));

user.setResume(Hibernate.createClob(" "));

Transaction tx = session.beginTransaction();

session.save(user);

session.flush();//强制Hibernate立即执行insert操作

STEP 2:

//强制Hibernate执行select for update

session.refresh(user, LockMode.UPGRADE);

//获得Lob字段的操作句柄

oracle.sql.BLOB image = (oracle.sql.BLOB)user.getImage();

oracle.sql.CLOB resume =(oracel.sql.CLOB)user.getResume();

//将文本写入Clob

java.io.Writer writer = resume.getCharacterOutputStream();

writer.writer("this is my resume");

writer.close();

//将图片写入Blob,不是直接对image操作而是先获得它的一个OutputStream

同一般的JDBC

STEP 3:

session.save(user);

tx.commit();

读操作同SQL SERVER 一样

Hibernate通过Session.save/flush/refresh方法的组合使用实现了上面JDBC代码中的lob访问逻辑

要注意的是:Oracle Thin Driver对Clob字段支持尚有欠缺,Clob字段超出4000字将无法读取

另外要注意的是: 

java.sql.Blob 
oracle.sql.BLOB 

注意看blob的大小写,是不一样的。写程序的时候不要搞混了

参考:http://hi.baidu.com/lylianyu/blog/item/e87e980968b5fb2d6a60fb24.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值