使用jdbc与hibernate将BLOB字段写入数据库

本文介绍如何使用 JDBC 和 Hibernate 在 Oracle 数据库中处理 Blob 类型数据。通过分步操作实现 Blob 的插入与更新,包括创建空 Blob、获取 Blob 游标及写入数据等关键步骤。

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

Oracle的Blob字段比较特殊,他比long字段的性能要好很多,可以用来保存例如图片之类的二进制数据。

写入Blob字段和写入其它类型字段的方式非常不同,因为Blob自身有一个cursor,你必须使用cursor对blob进行操作,因而你在写入Blob之前,必须获得cursor才能进行写入,那么如何获得Blob的cursor呢?

这需要你先插入一个empty的blob,这将创建一个blob的cursor,然后你再把这个empty的blob的cursor用select查询出来,这样通过两步操作,你就获得了blob的cursor,可以真正的写入blob数据了。

看下面的JDBC的demo,把oraclejdbc.jar这个二进制文件写入数据库表javatest的content字段(这是一个blob型字段)

  1. importjava.sql.*;
  2. importjava.io.*;
  3. importoracle.sql.*;
  4. publicclassWriteBlob{
  5. publicstaticvoidmain(String[]args){
  6. try{
  7. DriverManager.registerDriver(neworacle.jdbc.driver.OracleDriver());
  8. Connectionconn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl","fankai","fankai");
  9. conn.setAutoCommit(false);
  10. BLOBblob=null;
  11. PreparedStatementpstmt=conn.prepareStatement("insertintojavatest(name,content)values(?,empty_blob())");
  12. pstmt.setString(1,"fankai");
  13. pstmt.executeUpdate();
  14. pstmt.close();
  15. pstmt=conn.prepareStatement("selectcontentfromjavatestwherename=?forupdate");
  16. pstmt.setString(1,"fankai");
  17. ResultSetrset=pstmt.executeQuery();
  18. if(rset.next())blob=(BLOB)rset.getBlob(1);
  19. StringfileName="oraclejdbc.jar";
  20. Filef=newFile(fileName);
  21. FileInputStreamfin=newFileInputStream(f);
  22. System.out.println("filesize="+fin.available());
  23. pstmt=conn.prepareStatement("updatejavatestsetcontent=?wherename=?");
  24. OutputStreamout=blob.getBinaryOutputStream();
  25. intcount=-1,total=0;
  26. byte[]data=newbyte[(int)fin.available()];
  27. fin.read(data);
  28. out.write(data);
  29. /*
  30. byte[]data=newbyte[blob.getBufferSize()];另一种实现方法,节省内存
  31. while((count=fin.read(data))!=-1){
  32. total+=count;
  33. out.write(data,0,count);
  34. }
  35. */
  36. fin.close();
  37. out.close();
  38. pstmt.setBlob(1,blob);
  39. pstmt.setString(2,"fankai");
  40. pstmt.executeUpdate();
  41. pstmt.close();
  42. conn.commit();
  43. conn.close();
  44. }catch(SQLExceptione){
  45. System.err.println(e.getMessage());
  46. e.printStackTrace();
  47. }catch(IOExceptione){
  48. System.err.println(e.getMessage());
  49. }
  50. }
  51. }

仔细看上例,分三步:

1、插入空blob
into javatest(name,content) values(?,empty_blob());

2、获得blob的cursor
select content from javatest where name= ? for update;

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

3、update javatest set content=? where name=

用cursor往数据库写数据

这里面还有一点要提醒大家:

JDK1.3带的JDBC2.0规范是不完善的,只有读Blob的接口,而没有写Blob的接口,JDK1.4带的JDBC3.0加入了写Blob的接口。你可以使用JDBC3.0的接口,也可以直接使用Oracle的JDBC的API,我在上例中使用了Oracle的JDBC的API。

另外要注意的是:

java.sql.Blob
oracle.sql.BLOB

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

下面看看用Hibernate怎么写,原理是一样的,也要分三步,但是代码简单很多

这是Cat对象定义

  1. packagecom.fankai;
  2. importjava.sql.Blob;
  3. publicclassCat{
  4. privateStringid;
  5. privateStringname;
  6. privatecharsex;
  7. privatefloatweight;
  8. privateBlobimage;
  9. publicCat(){}
  10. publicStringgetId(){returnid;}
  11. publicvoidsetId(Stringid){this.id=id;}
  12. publicStringgetName(){returnname;}
  13. publicvoidsetName(Stringname){this.name=name;}
  14. publicchargetSex(){returnsex;}
  15. publicvoidsetSex(charsex){this.sex=sex;}
  16. publicfloatgetWeight(){returnweight;}
  17. publicvoidsetWeight(floatweight){this.weight=weight;}
  18. publicBlobgetImage(){returnimage;}
  19. publicvoidsetImage(Blobimage){this.image=image;}
  20. }

这是Cat.hbm.xml

  1. <?xmlversion="1.0"?>
  2. <!DOCTYPEhibernate-mappingSYSTEM"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
  3. <hibernate-mapping>
  4. <classname="com.fankai.Cat"table="cat">
  5. <!--jcs-cacheusage="read-only"/-->
  6. <idname="id"unsaved-value="null">
  7. <generatorclass="uuid.hex"/>
  8. </id>
  9. <propertyname="name"length="16"not-null="true"/>
  10. <propertyname="sex"length="1"not-null="true"/>
  11. <propertyname="weight"/>
  12. <propertyname="image"/>
  13. </class>
  14. </hibernate-mapping>

下面是完整的用Hibernate写入Blob的例子,相比JDBC,已经简单轻松多了,也不用写那些Oracle特殊的sql了:

  1. packagecom.fankai;
  2. importjava.sql.Blob;
  3. importnet.sf.hibernate.*;
  4. importoracle.sql.*;
  5. importjava.io.*;
  6. publicclassTestCatHibernate{
  7. publicstaticvoidtestBlob(){
  8. Sessions=null;
  9. byte[]buffer=newbyte[1];
  10. buffer[0]=1;
  11. try{
  12. SessionFactorysf=HibernateSessionFactory.getSessionFactory();
  13. s=sf.openSession();
  14. Transactiontx=s.beginTransaction();
  15. Catc=newCat();
  16. c.setName("Robbin");
  17. c.setImage(Hibernate.createBlob(buffer));
  18. s.save(c);
  19. s.flush();
  20. s.refresh(c,LockMode.UPGRADE);
  21. BLOBblob=(BLOB)c.getImage();
  22. OutputStreamout=blob.getBinaryOutputStream();
  23. StringfileName="oraclejdbc.jar";
  24. Filef=newFile(fileName);
  25. FileInputStreamfin=newFileInputStream(f);
  26. intcount=-1,total=0;
  27. byte[]data=newbyte[(int)fin.available()];
  28. fin.read(data);
  29. out.write(data);
  30. fin.close();
  31. out.close();
  32. s.flush();
  33. tx.commit();
  34. }catch(Exceptione){
  35. System.out.println(e.getMessage());
  36. }finally{
  37. if(s!=null)
  38. try{
  39. s.close();
  40. }catch(Exceptione){}
  41. }
  42. }
  43. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值