好學驛站

          JSP、JAVA、struts、hibernate、spring、eclipse、工作流、電子政務、協同辦公、J2ME

          用JDBC和HIBERNATE寫入ORACLE的blog字段

          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. import ?java.sql.*; ??
          2. import ?java.io.*; ??
          3. import ?oracle.sql.*; ??
          4. public ? class ?WriteBlob?{ ??
          5. ??
          6. ?? public ? static ? void ?main(String[]?args)?{ ??
          7. ??
          8. ???? try ?{ ??
          9. ??????DriverManager.registerDriver( new ?oracle.jdbc.driver.OracleDriver()); ??
          10. ??????Connection?conn?=?DriverManager.getConnection( "jdbc:oracle:thin:@localhost:1521:orcl" , "fankai" , "fankai" ); ??
          11. ??????conn.setAutoCommit( false ); ??
          12. ??
          13. ??????BLOB?blob?=? null ; ??
          14. ??
          15. ??????PreparedStatement?pstmt?=?conn.prepareStatement( "insert?into?javatest(name,content)?values(?,empty_blob())" ); ??
          16. ??????pstmt.setString( 1 , "fankai" ); ??
          17. ??????pstmt.executeUpdate(); ??
          18. ??????pstmt.close(); ??
          19. ??
          20. ??????pstmt?=?conn.prepareStatement( "select?content?from?javatest?where?name=???for?update" ); ??
          21. ??????pstmt.setString( 1 , "fankai" ); ??
          22. ??????ResultSet?rset?=?pstmt.executeQuery(); ??
          23. ?????? if ?(rset.next())?blob?=?(BLOB)?rset.getBlob( 1 ); ??
          24. ??
          25. ??????String?fileName?=? "oraclejdbc.jar" ; ??
          26. ??????File?f?=? new ?File(fileName); ??
          27. ??????FileInputStream?fin?=? new ?FileInputStream(f); ??
          28. ??????System.out.println( "file?size?=?" ?+?fin.available()); ??
          29. ??
          30. ??????pstmt?=?conn.prepareStatement( "update?javatest?set?content=??where?name=?" ); ??
          31. ??
          32. ??????OutputStream?out?=?blob.getBinaryOutputStream(); ??
          33. ??
          34. ?????? int ?count?=?- 1 ,?total?=? 0 ; ??
          35. ?????? byte []?data?=? new ? byte [( int )fin.available()]; ??
          36. ??????fin.read(data); ??
          37. ??????out.write(data); ??
          38. ?????? /* ?
          39. ??????byte[]?data?=?new?byte[blob.getBufferSize()];??另一種實現方法,節省內存 ?
          40. ??????while?((count?=?fin.read(data))?!=?-1)?{ ?
          41. ????????total?+=?count; ?
          42. ????????out.write(data,?0,?count); ?
          43. ??????} ?
          44. ??????*/ ??
          45. ??
          46. ??????fin.close(); ??
          47. ??????out.close(); ??
          48. ??
          49. ??????pstmt.setBlob( 1 ,blob); ??
          50. ??????pstmt.setString( 2 , "fankai" ); ??
          51. ??
          52. ??????pstmt.executeUpdate(); ??
          53. ??????pstmt.close(); ??
          54. ??
          55. ??????conn.commit(); ??
          56. ??????conn.close(); ??
          57. ????}? catch ?(SQLException?e)?{ ??
          58. ??????System.err.println(e.getMessage()); ??
          59. ??????e.printStackTrace(); ??
          60. ????}? catch ?(IOException?e)?{ ??
          61. ??????System.err.println(e.getMessage()); ??
          62. ????} ??
          63. ??} ??
          64. ??
          65. }??

          仔細看上例,分三步:

          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. package ?com.fankai; ??
          2. ??
          3. import ?java.sql.Blob; ??
          4. ??
          5. public ? class ?Cat?{ ??
          6. ?? private ?String?id; ??
          7. ?? private ?String?name; ??
          8. ?? private ? char ?sex; ??
          9. ?? private ? float ?weight; ??
          10. ?? private ?Blob?image; ??
          11. ?? public ?Cat()?{?} ??
          12. ??
          13. ?? public ?String?getId()?{? return ?id;?} ??
          14. ?? public ? void ?setId(String?id)?{? this .id?=?id;?} ??
          15. ??
          16. ?? public ?String?getName()?{? return ?name;?} ??
          17. ?? public ? void ?setName(String?name)?{? this .name?=?name;?} ??
          18. ??
          19. ?? public ? char ?getSex()?{? return ?sex;?} ??
          20. ?? public ? void ?setSex( char ?sex)?{? this .sex?=?sex;?} ??
          21. ??
          22. ?? public ? float ?getWeight()?{? return ?weight;?} ??
          23. ?? public ? void ?setWeight( float ?weight)?{? this .weight?=?weight;?} ??
          24. ?? ??
          25. ?? public ?Blob?getImage()?{? return ?image;?} ??
          26. ?? public ? void ?setImage(Blob?image)?{? this .image?=?image;} ??
          27. }??

          這是Cat.hbm.xml

          代碼
          1. <? xml ? version = "1.0" ?> ??
          2. <!DOCTYPE?hibernate-mapping?SYSTEM?"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" > ??
          3. ??
          4. < hibernate-mapping > ??
          5. ???? < class ? name = "com.fankai.Cat" ? table = "cat" > ??
          6. ???????? <!--jcs-cache?usage="read-only"/--> ??
          7. ???????? < id ? name = "id" ? unsaved-value = "null" > ??
          8. ???????????? < generator ? class = "uuid.hex" /> ??
          9. ???????? </ id > ??
          10. ???????? < property ? name = "name" ? length = "16" ? not-null = "true" /> ??
          11. ???????? < property ? name = "sex" ? length = "1" ? not-null = "true" /> ??
          12. ???????? < property ? name = "weight" ? /> ??
          13. ???????? < property ? name = "image" ? /> ??
          14. ???? </ class > ??
          15. </ hibernate-mapping > ??

          下面是完整的用Hibernate寫入Blob的例子,相比JDBC,已經簡單輕松多了,也不用寫那些Oracle特殊的sql了:

          代碼
          1. package ?com.fankai; ??
          2. ??
          3. import ?java.sql.Blob; ??
          4. import ?net.sf.hibernate.*; ??
          5. import ?oracle.sql.*; ??
          6. import ?java.io.*; ??
          7. ??
          8. public ? class ?TestCatHibernate?{?? ??
          9. ?? public ? static ? void ?testBlob()?{ ??
          10. ????Session?s?=? null ;???? ??
          11. ???? byte []?buffer?=? new ? byte [ 1 ]; ??
          12. ????buffer[ 0 ]?=? 1 ; ??
          13. ???? try ?{ ??
          14. ??????SessionFactory?sf?=?HibernateSessionFactory.getSessionFactory(); ??
          15. ??????s?=?sf.openSession();?? ??
          16. ??????Transaction?tx?=?s.beginTransaction(); ??
          17. ??????Cat?c?=? new ?Cat(); ??
          18. ??????c.setName( "Robbin" ); ??
          19. ??????c.setImage(Hibernate.createBlob(buffer)); ??
          20. ??????s.save(c); ??
          21. ??????s.flush(); ??
          22. ??????s.refresh(c,?LockMode.UPGRADE);???? ??
          23. ??????BLOB?blob?=?(BLOB)?c.getImage();?????? ??
          24. ??????OutputStream?out?=?blob.getBinaryOutputStream();??? ??
          25. ??????String?fileName?=? "oraclejdbc.jar" ; ??
          26. ??????File?f?=? new ?File(fileName); ??
          27. ??????FileInputStream?fin?=? new ?FileInputStream(f);??? ??
          28. ?????? int ?count?=?- 1 ,?total?=? 0 ; ??
          29. ?????? byte []?data?=? new ? byte [( int )fin.available()]; ??
          30. ??????fin.read(data); ??
          31. ??????out.write(data);?????? ??
          32. ??????fin.close(); ??
          33. ??????out.close(); ??
          34. ??????s.flush(); ??
          35. ??????tx.commit(); ??
          36. ??? ??
          37. ????}? catch ?(Exception?e)?{ ??
          38. ??????System.out.println(e.getMessage()); ??
          39. ????}? finally ?{ ??
          40. ?????? if ?(s?!=? null ) ??
          41. ???????? try ?{ ??
          42. ??????????s.close(); ??
          43. ????????}? catch ?(Exception?e)?{} ??
          44. ????}???? ??
          45. ???? ??
          46. ??} ??
          47. }??

          posted on 2007-06-13 11:02 好學蜘蛛 閱讀(248) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 泾阳县| 垫江县| 张掖市| 长沙市| 松潘县| 肇庆市| 广水市| 顺义区| 都安| 璧山县| 兴海县| 唐河县| 台江县| 深水埗区| 新兴县| 三原县| 普陀区| 永定县| 金门县| 宣恩县| 香河县| 马公市| 霸州市| 吉隆县| 曲周县| 堆龙德庆县| 西盟| 腾冲县| 德州市| 牡丹江市| 肇源县| 山丹县| 安义县| 同心县| 正阳县| 桑日县| 博兴县| 营山县| 五原县| 浏阳市| 宜川县|