用JDBC和HIBERNATE寫入ORACLE的blog字段
Oracle的Blob字段比較特殊,他比long字段的性能要好很多,可以用來保存例如圖片之類的二進制數(shù)據(jù)。
寫入Blob字段和寫入其它類型字段的方式非常不同,因為Blob自身有一個cursor,你必須使用cursor對blob進行操作,因而你在寫入Blob之前,必須獲得cursor才能進行寫入,那么如何獲得Blob的cursor呢?
這需要你先插入一個empty的blob,這將創(chuàng)建一個blob的cursor,然后你再把這個empty的blob的cursor用select查詢出來,這樣通過兩步操作,你就獲得了blob的cursor,可以真正的寫入blob數(shù)據(jù)了。
看下面的JDBC的demo,把oraclejdbc.jar這個二進制文件寫入數(shù)據(jù)庫表javatest的content字段(這是一個blob型字段)
- import ?java.sql.*; ??
- import ?java.io.*; ??
- import ?oracle.sql.*; ??
- public ? class ?WriteBlob?{ ??
- ??
- ?? public ? static ? void ?main(String[]?args)?{ ??
- ??
- ???? try ?{ ??
- ??????DriverManager.registerDriver( new ?oracle.jdbc.driver.OracleDriver()); ??
- ??????Connection?conn?=?DriverManager.getConnection( "jdbc:oracle:thin:@localhost:1521:orcl" , "fankai" , "fankai" ); ??
- ??????conn.setAutoCommit( false ); ??
- ??
- ??????BLOB?blob?=? null ; ??
- ??
- ??????PreparedStatement?pstmt?=?conn.prepareStatement( "insert?into?javatest(name,content)?values(?,empty_blob())" ); ??
- ??????pstmt.setString( 1 , "fankai" ); ??
- ??????pstmt.executeUpdate(); ??
- ??????pstmt.close(); ??
- ??
- ??????pstmt?=?conn.prepareStatement( "select?content?from?javatest?where?name=???for?update" ); ??
- ??????pstmt.setString( 1 , "fankai" ); ??
- ??????ResultSet?rset?=?pstmt.executeQuery(); ??
- ?????? if ?(rset.next())?blob?=?(BLOB)?rset.getBlob( 1 ); ??
- ??
- ??????String?fileName?=? "oraclejdbc.jar" ; ??
- ??????File?f?=? new ?File(fileName); ??
- ??????FileInputStream?fin?=? new ?FileInputStream(f); ??
- ??????System.out.println( "file?size?=?" ?+?fin.available()); ??
- ??
- ??????pstmt?=?conn.prepareStatement( "update?javatest?set?content=??where?name=?" ); ??
- ??
- ??????OutputStream?out?=?blob.getBinaryOutputStream(); ??
- ??
- ?????? int ?count?=?- 1 ,?total?=? 0 ; ??
- ?????? byte []?data?=? new ? byte [( int )fin.available()]; ??
- ??????fin.read(data); ??
- ??????out.write(data); ??
- ?????? /* ?
- ??????byte[]?data?=?new?byte[blob.getBufferSize()];??另一種實現(xiàn)方法,節(jié)省內(nèi)存 ?
- ??????while?((count?=?fin.read(data))?!=?-1)?{ ?
- ????????total?+=?count; ?
- ????????out.write(data,?0,?count); ?
- ??????} ?
- ??????*/ ??
- ??
- ??????fin.close(); ??
- ??????out.close(); ??
- ??
- ??????pstmt.setBlob( 1 ,blob); ??
- ??????pstmt.setString( 2 , "fankai" ); ??
- ??
- ??????pstmt.executeUpdate(); ??
- ??????pstmt.close(); ??
- ??
- ??????conn.commit(); ??
- ??????conn.close(); ??
- ????}? catch ?(SQLException?e)?{ ??
- ??????System.err.println(e.getMessage()); ??
- ??????e.printStackTrace(); ??
- ????}? catch ?(IOException?e)?{ ??
- ??????System.err.println(e.getMessage()); ??
- ????} ??
- ??} ??
- ??
- }??
仔細看上例,分三步:
1、插入空blob
into javatest(name,content) values(?,empty_blob());
2、獲得blob的cursor
select content from javatest where name= ? for update;
注意!!!必須加for update,這將鎖定該行,直至該行被修改完畢,保證不產(chǎn)生并發(fā)沖突。
3、update javatest set content=? where name=
用cursor往數(shù)據(jù)庫寫數(shù)據(jù)
這里面還有一點要提醒大家:
JDK1.3帶的JDBC2.0規(guī)范是不完善的,只有讀Blob的接口,而沒有寫B(tài)lob的接口,JDK1.4帶的JDBC3.0加入了寫B(tài)lob的接口。你可以使用JDBC3.0的接口,也可以直接使用Oracle的JDBC的API,我在上例中使用了Oracle的JDBC的API。
另外要注意的是:
java.sql.Blob
oracle.sql.BLOB
注意看blob的大小寫,是不一樣的。寫程序的時候不要搞混了。
下面看看用Hibernate怎么寫,原理是一樣的,也要分三步,但是代碼簡單很多
這是Cat對象定義
- package ?com.fankai; ??
- ??
- import ?java.sql.Blob; ??
- ??
- public ? class ?Cat?{ ??
- ?? private ?String?id; ??
- ?? private ?String?name; ??
- ?? private ? char ?sex; ??
- ?? private ? float ?weight; ??
- ?? private ?Blob?image; ??
- ?? public ?Cat()?{?} ??
- ??
- ?? public ?String?getId()?{? return ?id;?} ??
- ?? public ? void ?setId(String?id)?{? this .id?=?id;?} ??
- ??
- ?? public ?String?getName()?{? return ?name;?} ??
- ?? public ? void ?setName(String?name)?{? this .name?=?name;?} ??
- ??
- ?? public ? char ?getSex()?{? return ?sex;?} ??
- ?? public ? void ?setSex( char ?sex)?{? this .sex?=?sex;?} ??
- ??
- ?? public ? float ?getWeight()?{? return ?weight;?} ??
- ?? public ? void ?setWeight( float ?weight)?{? this .weight?=?weight;?} ??
- ?? ??
- ?? public ?Blob?getImage()?{? return ?image;?} ??
- ?? public ? void ?setImage(Blob?image)?{? this .image?=?image;} ??
- }??
這是Cat.hbm.xml
- <? xml ? version = "1.0" ?> ??
- <!DOCTYPE?hibernate-mapping?SYSTEM?"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" > ??
- ??
- < hibernate-mapping > ??
- ???? < class ? name = "com.fankai.Cat" ? table = "cat" > ??
- ???????? <!--jcs-cache?usage="read-only"/--> ??
- ???????? < id ? name = "id" ? unsaved-value = "null" > ??
- ???????????? < generator ? class = "uuid.hex" /> ??
- ???????? </ id > ??
- ???????? < property ? name = "name" ? length = "16" ? not-null = "true" /> ??
- ???????? < property ? name = "sex" ? length = "1" ? not-null = "true" /> ??
- ???????? < property ? name = "weight" ? /> ??
- ???????? < property ? name = "image" ? /> ??
- ???? </ class > ??
- </ hibernate-mapping > ??
下面是完整的用Hibernate寫入Blob的例子,相比JDBC,已經(jīng)簡單輕松多了,也不用寫那些Oracle特殊的sql了:
- package ?com.fankai; ??
- ??
- import ?java.sql.Blob; ??
- import ?net.sf.hibernate.*; ??
- import ?oracle.sql.*; ??
- import ?java.io.*; ??
- ??
- public ? class ?TestCatHibernate?{?? ??
- ?? public ? static ? void ?testBlob()?{ ??
- ????Session?s?=? null ;???? ??
- ???? byte []?buffer?=? new ? byte [ 1 ]; ??
- ????buffer[ 0 ]?=? 1 ; ??
- ???? try ?{ ??
- ??????SessionFactory?sf?=?HibernateSessionFactory.getSessionFactory(); ??
- ??????s?=?sf.openSession();?? ??
- ??????Transaction?tx?=?s.beginTransaction(); ??
- ??????Cat?c?=? new ?Cat(); ??
- ??????c.setName( "Robbin" ); ??
- ??????c.setImage(Hibernate.createBlob(buffer)); ??
- ??????s.save(c); ??
- ??????s.flush(); ??
- ??????s.refresh(c,?LockMode.UPGRADE);???? ??
- ??????BLOB?blob?=?(BLOB)?c.getImage();?????? ??
- ??????OutputStream?out?=?blob.getBinaryOutputStream();??? ??
- ??????String?fileName?=? "oraclejdbc.jar" ; ??
- ??????File?f?=? new ?File(fileName); ??
- ??????FileInputStream?fin?=? new ?FileInputStream(f);??? ??
- ?????? int ?count?=?- 1 ,?total?=? 0 ; ??
- ?????? byte []?data?=? new ? byte [( int )fin.available()]; ??
- ??????fin.read(data); ??
- ??????out.write(data);?????? ??
- ??????fin.close(); ??
- ??????out.close(); ??
- ??????s.flush(); ??
- ??????tx.commit(); ??
- ??? ??
- ????}? catch ?(Exception?e)?{ ??
- ??????System.out.println(e.getMessage()); ??
- ????}? finally ?{ ??
- ?????? if ?(s?!=? null ) ??
- ???????? try ?{ ??
- ??????????s.close(); ??
- ????????}? catch ?(Exception?e)?{} ??
- ????}???? ??
- ???? ??
- ??} ??
- }??