2007-04-16?? 版權聲明
我知道這篇文章閱讀量很大,但是請要繼續轉載本文的同志注意一下,本文是我在 2005 年春節期間寫的,春節是合家團圓的日子,所以在這個時候寫點東西不容易,整整花了我將近 20 天的時間啊。請保留原文版權信息 OK?
----------------------------------------------------------------------------------------------------
在存儲圖片、可執行文件等二進制信息時(當然直接放在文件系統上也行), BLOB 數據就派上用場了。 本文無 太多 深度可言,能為大家在開發過程中提供參考足亦!
Hibernate 與 SQL Server BLOB
BLOB 數據在 SQL Server 數據庫中主要由 IMAGE 類型體現,最大容量為 2GB 。其存儲方式不同于普通的數據類型,對于普通類型的數據系統直接在用戶定義的字段上存儲數據值,而對于 IMAGE 類型數據,系統開辟新的存儲頁面來存放這些數據,表中 IMAGE 類型數據字段存放的僅是一個 16 字節的指針,該指針指向存放該條記錄的 IMAGE 數據的頁面。如果 你對 Hibernate 還不熟息,請看 這里 。
新建名為 “BLOB_TEST” 的表,字段分別是 INT 類型的 “ID” 和 IMAGE 類型的 “MYBLOB” 。從文件系統讀取 “sample.jpg” 并轉換成字節數組再放進 BlobTest 對象實例。 寫入程序如下:
import java.io.*; import net.sf.hibernate.*;import net.sf.hibernate.cfg.*; import bo.*; public class Tester { ?public void DoTest() {??InputStream in = null;??BlobTest blobTest = null;??Configuration cfg = null;??SessionFactory sessions = null;??Session session = null;??Transaction tx = null;??try {???//begin InputStream???in = new FileInputStream("d:/sample.jpg");???byte[] b = new byte[in.available()];???in.read(b);???in.close(); ???//begin BlobTest???blobTest = new BlobTest();???blobTest.setMyblob(b); ???//begin Hibernate Session???cfg = new Configuration().configure();???sessions = cfg.buildSessionFactory();???session = sessions.openSession();???tx = session.beginTransaction();???session.save(blobTest);???tx.commit();??} catch (Exception e) {???e.printStackTrace();??} finally {???try {????session.close();???} catch (Exception e1) {????e1.printStackTrace();???}??}?}} ?
import java.io.*;
import net.sf.hibernate.*;import net.sf.hibernate.cfg.*;
import bo.*;
public class Tester {
?public void DoTest() {??InputStream in = null;??BlobTest blobTest = null;??Configuration cfg = null;??SessionFactory sessions = null;??Session session = null;??Transaction tx = null;??try {???//begin InputStream???in = new FileInputStream("d:/sample.jpg");???byte[] b = new byte[in.available()];???in.read(b);???in.close();
???//begin BlobTest???blobTest = new BlobTest();???blobTest.setMyblob(b);
???//begin Hibernate Session???cfg = new Configuration().configure();???sessions = cfg.buildSessionFactory();???session = sessions.openSession();???tx = session.beginTransaction();???session.save(blobTest);???tx.commit();??} catch (Exception e) {???e.printStackTrace();??} finally {???try {????session.close();???} catch (Exception e1) {????e1.printStackTrace();???}??}?}}
取出 程序如下:
import java.io.*; import net.sf.hibernate.*;import net.sf.hibernate.cfg.*; import bo.*; public class Tester { ?public void DoTest() {??OutputStream out = null;??BlobTest blobTest = null;??Configuration cfg = null;??SessionFactory sessions = null;??Session session = null;??try {???//begin Hibernate Session???cfg = new Configuration().configure();???sessions = cfg.buildSessionFactory();???session = sessions.openSession(); ???//begin BlobTest???blobTest = new BlobTest();???blobTest = (BlobTest) session.load(BlobTest.class, new Integer(23)); ???//begin OutputStream???out = new FileOutputStream("d:/sample.jpg");???out.write(blobTest.getMyblob());???out.flush();???out.close();??} catch (Exception e) {???e.printStackTrace();??} finally {???try {????session.close();???} catch (Exception e1) {????e1.printStackTrace();???}??}?}} ??
?public void DoTest() {??OutputStream out = null;??BlobTest blobTest = null;??Configuration cfg = null;??SessionFactory sessions = null;??Session session = null;??try {???//begin Hibernate Session???cfg = new Configuration().configure();???sessions = cfg.buildSessionFactory();???session = sessions.openSession();
???//begin BlobTest???blobTest = new BlobTest();???blobTest = (BlobTest) session.load(BlobTest.class, new Integer(23));
???//begin OutputStream???out = new FileOutputStream("d:/sample.jpg");???out.write(blobTest.getMyblob());???out.flush();???out.close();??} catch (Exception e) {???e.printStackTrace();??} finally {???try {????session.close();???} catch (Exception e1) {????e1.printStackTrace();???}??}?}}
Hibernate 與 MySQL BLOB
??? MySQL 中的 BLOB 數據由四種類型體現,分別是 TINYBLOB 其容量為 256 字節、 BLOB 其容量為 64KB 、 MEDIUMBLOB 其容量為 16MB 、 LONGBLOB 其容量為 4GB 。
新建名為 “BLOB_TEST” 的表,字段分別是 INTEGER 類型的 “ID” 和 MEDIUMBLOB 類型的 “MYBLOB” 。從文件系統讀取 “sample.jpg” 并轉換成字節數組再放進 BlobTest 對象實例。 寫入、 取出 程序和上面的 SQL Server 一樣。
Hibernate 與 Oracle BLOB
??? 為了不使用 “for update” 鎖住數據庫,遂打算讓 Oracle LONG RAW 類型保存大對象,最大容量 2GB 。經過測試后發現,直接寫 JDBC 代碼可以保存,但 Hibernate 只能保存 4K 大小內容,換成 Hibernate 3.0 beta3 也未能成功。偶然的機會在郵件列表上發現這是 JDBC Driver 的問題,換成 Oracle 10g 的驅動后問題解決。
新建名為 “BLOB_TEST” 的表,字段分別是 NUMBER 類型的 “ID” 和 LONG RAW 類型的 “MYBLOB” 。從文件系統讀取 “sample.jpg” 并轉換成字節數組再放進 BlobTest 對象實例。 寫入、 取出 程序和 SQL Server 一樣。
如果你一定要用 Oracle BLOB 類型,接著往下看:
??? Hibernate 處理 Oracle BLOB 類型較特殊 , 從文件系統讀取 “sample.jpg” 放進 BlobTest 對象實例的是 java.sql.Blob 類型,而不是字節數組。
import java.io.*; import net.sf.hibernate.*;import net.sf.hibernate.cfg.*;import oracle.sql.*; import bo.*; public class Tester { ?public void DoTest() {??BLOB blob = null;??InputStream in = null;??OutputStream out = null;??BlobTest blobTest = null;??Configuration cfg = null;??SessionFactory sessions = null;??Session session = null;??Transaction tx = null;??try {???//begin InputStream???in = new FileInputStream("d:/sample.jpg");???byte[] b = new byte[in.available()];???in.read(b);???in.close();??????//begin BlobTest???blobTest = new BlobTest();???blobTest.setMyblob(BLOB.empty_lob());??????//begin Hibernate Session???cfg = new Configuration().configure();???sessions = cfg.buildSessionFactory();???session = sessions.openSession();???tx = session.beginTransaction();???session.save(blobTest);???session.flush();???session.refresh(blobTest, LockMode.UPGRADE);???blob = (BLOB) blobTest.getMyblob(); ???out = blob.getBinaryOutputStream();???out.write(b);???out.close();???session.flush();???tx.commit();??} catch (Exception e) {???e.printStackTrace();??} finally {???try {????session.close();???} catch (Exception e1) {????e1.printStackTrace();???}??}?}} ??
import net.sf.hibernate.*;import net.sf.hibernate.cfg.*;import oracle.sql.*;
?public void DoTest() {??BLOB blob = null;??InputStream in = null;??OutputStream out = null;??BlobTest blobTest = null;??Configuration cfg = null;??SessionFactory sessions = null;??Session session = null;??Transaction tx = null;??try {???//begin InputStream???in = new FileInputStream("d:/sample.jpg");???byte[] b = new byte[in.available()];???in.read(b);???in.close();??????//begin BlobTest???blobTest = new BlobTest();???blobTest.setMyblob(BLOB.empty_lob());??????//begin Hibernate Session???cfg = new Configuration().configure();???sessions = cfg.buildSessionFactory();???session = sessions.openSession();???tx = session.beginTransaction();???session.save(blobTest);???session.flush();???session.refresh(blobTest, LockMode.UPGRADE);???blob = (BLOB) blobTest.getMyblob(); ???out = blob.getBinaryOutputStream();???out.write(b);???out.close();???session.flush();???tx.commit();??} catch (Exception e) {???e.printStackTrace();??} finally {???try {????session.close();???} catch (Exception e1) {????e1.printStackTrace();???}??}?}}
取出 程序和其他兩種數據庫操作幾乎一樣。 ?
iBATIS SQL Maps 與 SQL Server BLOB
??? 建表過程和 Hibernate 操作 SQL Server 一樣,如果 你對 iBATIS SQL Maps 還不熟息,請看 這里 。
映射文件如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMap??? PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"??? " http://www.ibatis.com/dtd/sql-map-2.dtd "> <sqlMap> ??? <insert id="insertBlob" parameterClass="bo.BlobTest">????? <![CDATA[ ??????? insert into blob_test (myblob) values (#myblob#)????? ]]>????? <selectKey resultClass="java.lang.Integer" keyProperty="id"> ??????? <![CDATA[ ????????? SELECT @@IDENTITY AS ID??????? ]]>????? </selectKey>??? </insert> ??? <resultMap id="get-blob-result" class="bo.BlobTest">????? <result property="id" column="id"/>????? <result property="myblob" column="myblob"/>??? </resultMap> ??? <select id="getBlob" resultMap="get-blob-result" parameterClass="bo.BlobTest">????? <![CDATA[ ??????? select * from blob_test where id=#id#????? ]]>??? </select>??????? </sqlMap> ? 寫入程序如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap??? PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"??? " http://www.ibatis.com/dtd/sql-map-2.dtd ">
<sqlMap>
??? <insert id="insertBlob" parameterClass="bo.BlobTest">????? <![CDATA[ ??????? insert into blob_test (myblob) values (#myblob#)????? ]]>????? <selectKey resultClass="java.lang.Integer" keyProperty="id"> ??????? <![CDATA[ ????????? SELECT @@IDENTITY AS ID??????? ]]>????? </selectKey>??? </insert>
??? <resultMap id="get-blob-result" class="bo.BlobTest">????? <result property="id" column="id"/>????? <result property="myblob" column="myblob"/>??? </resultMap>
??? <select id="getBlob" resultMap="get-blob-result" parameterClass="bo.BlobTest">????? <![CDATA[ ??????? select * from blob_test where id=#id#????? ]]>??? </select>??????? </sqlMap>
import java.io.*; import com.ibatis.sqlmap.client.*;import com.ibatis.common.resources.*; import bo.*; public class Tester { ?public void DoTest() {??byte[] b=null;??Reader reader = null;??InputStream in = null;??BlobTest blobTest = null;??SqlMapClient sqlMap = null;??String resource = "SqlMapConfig.xml";??try {???//begin InputStream ???in = new FileInputStream("d:/sample.jpg");???b = new byte[in.available()];???in.read(b);???in.close(); ???//begin BlobTest???blobTest = new BlobTest();???blobTest.setMyblob(b); ???//begin SqlMapClient???reader = Resources.getResourceAsReader(resource);???sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);???sqlMap.startTransaction();???sqlMap.insert("insertBlob", blobTest);???sqlMap.commitTransaction();??} catch (Exception e) {???e.printStackTrace();??} finally {???try {????sqlMap.endTransaction();???} catch (Exception e1) {????e1.printStackTrace();???}??}?}} ??取出程序如下:?? import java.io.*;import com.ibatis.sqlmap.client.*;import com.ibatis.common.resources.*;import bo.*;public class Tester {?public void DoTest() {??Reader reader = null;??OutputStream out = null;??BlobTest blobTest = null;??SqlMapClient sqlMap = null;??String resource = "SqlMapConfig.xml";??try {???//begin BlobTest???blobTest = new BlobTest();???blobTest.setId(new Integer(21));???//begin SqlMapClient???reader = Resources.getResourceAsReader(resource);???sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);???blobTest = (BlobTest) sqlMap.queryForObject("getBlob", blobTest);???//begin OutputStream???out = new FileOutputStream("d:/sample.jpg");???out.write(blobTest.getMyblob());???out.close();??} catch (Exception e) {???e.printStackTrace();??} finally {???try {????sqlMap.endTransaction();???} catch (Exception e1) {????e1.printStackTrace();???}??}?}}
import com.ibatis.sqlmap.client.*;import com.ibatis.common.resources.*;
?public void DoTest() {??byte[] b=null;??Reader reader = null;??InputStream in = null;??BlobTest blobTest = null;??SqlMapClient sqlMap = null;??String resource = "SqlMapConfig.xml";??try {???//begin InputStream ???in = new FileInputStream("d:/sample.jpg");???b = new byte[in.available()];???in.read(b);???in.close();
???//begin SqlMapClient???reader = Resources.getResourceAsReader(resource);???sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);???sqlMap.startTransaction();???sqlMap.insert("insertBlob", blobTest);???sqlMap.commitTransaction();??} catch (Exception e) {???e.printStackTrace();??} finally {???try {????sqlMap.endTransaction();???} catch (Exception e1) {????e1.printStackTrace();???}??}?}}
?public void DoTest() {??Reader reader = null;??OutputStream out = null;??BlobTest blobTest = null;??SqlMapClient sqlMap = null;??String resource = "SqlMapConfig.xml";??try {???//begin BlobTest???blobTest = new BlobTest();???blobTest.setId(new Integer(21));
???//begin SqlMapClient???reader = Resources.getResourceAsReader(resource);???sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);???blobTest = (BlobTest) sqlMap.queryForObject("getBlob", blobTest);
???//begin OutputStream???out = new FileOutputStream("d:/sample.jpg");???out.write(blobTest.getMyblob());???out.close();??} catch (Exception e) {???e.printStackTrace();??} finally {???try {????sqlMap.endTransaction();???} catch (Exception e1) {????e1.printStackTrace();???}??}?}}
iBATIS SQL Maps 與 MySQL BLOB
??? 這個主題很簡單,需要注意映射文件 insert 元素主鍵生成方式, 寫入、 取出 程序和上面的 SQL Server 一樣 :
??? <insert id="insertBlob" parameterClass="bo.BlobTest">????? <![CDATA[ ??????? insert into blob_test (myblob) values (#myblob#)????? ]]>????? <selectKey resultClass="java.lang.Integer" keyProperty="id">??? <![CDATA[????????? select last_insert_id();??? ]]>????? </selectKey>? </insert> ?
iBATIS SQL Maps 與 Oracle BLOB
??? 使用 Oracle LONG RAW 類型, 注意映射文件 insert 元素主鍵生成方式, 寫入、 取出 程序和上面的 SQL Server 一樣 :
??? <insert id="insertBlob" parameterClass="bo.BlobTest">????? <selectKey resultClass="int" keyProperty="id"> ??????? <![CDATA[ ????????? select hibernate_sequence.nextval from dual??????? ]]>????? </selectKey>????? <![CDATA[ ??????? insert into blob_test (id,myblob) values (#id#,#myblob#)????? ]]>??? </insert> ?
??? <insert id="insertBlob" parameterClass="bo.BlobTest">????? <selectKey resultClass="int" keyProperty="id"> ??????? <![CDATA[ ????????? select hibernate_sequence.nextval from dual??????? ]]>????? </selectKey>????? <![CDATA[ ??????? insert into blob_test (id,myblob) values (#id#,#myblob#)????? ]]>??? </insert>
??? 在 iBATIS 2.0.9 以前,處理 Oracle BLOB 類型相當麻煩,要自己實現 TypeHandlerCallback 接口。 iBATIS 2.0.9 提供了 BlobTypeHandlerCallback 實現類,寫入、 取出 程序和上面的 SQL Server 一樣。只是映射文件 resultMap 元素 需要修改: ??? <resultMap id="get-blob-result" class="bo.BlobTest">????? <result property="id" column="id"/>????? <result property="myblob" column="myblob"????????????? typeHandler="com.ibatis.sqlmap.engine.type.BlobTypeHandlerCallback"/>??? </resultMap> 應廣大開發者的要求,我把BlobTest類源代碼提交上來,當年用的是插件生成,一共有三個文件:
?
如果還有什么問題,請留言。(2007-10-11 by rosen jiang) 請注意!引用、轉貼本文應注明原作者:Rosen Jiang 以及出處: http://www.tkk7.com/rosen
Powered by: BlogJava Copyright © Rosen