成都心情

  BlogJava :: 首页 ::  :: 联系 :: 聚合  :: 管理 ::
  98 随笔 :: 2 文章 :: 501 评论 :: 1 Trackbacks

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() {
  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();
   }
  }
 }
}

  

取出 程序和其他两种数据库操作几乎一样。
 

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>

 
写入程序如下:

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();
   }
  }
 }
}


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>

 

如果你一定要用 Oracle BLOB 类型,接着往下看:

    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类源代码提交上来,当年用的是插件生成,一共有三个文件:

package  old;

import  java.io.Serializable;


/**
 * This class has been automatically generated by Hibernate Synchronizer.
 * For more information or documentation, visit The Hibernate Synchronizer page
 * at 
http://www.binamics.com/hibernatesync  or contact Joe Hudson at joe@binamics.com.
 *
 * This is an object that contains data related to the BLOB_TEST table.
 * Do not modify this class because it will be overwritten if the configuration file
 * related to this class is modified.
 *
 * @hibernate.class
 *  table="BLOB_TEST"
 
*/
public   abstract   class  BaseBlobTest   implements  Serializable {

    
public   static  String PROP_MYBLOB  =   " Myblob " ;
    
public   static  String PROP_ID  =   " Id " ;


    
private   int  hashCode  =  Integer.MIN_VALUE;

    
//  primary key
     private  java.lang.Integer _id;

    
//  fields
     private  java.sql.Blob _myblob;


    
//  constructors
     public  BaseBlobTest () {
        initialize();
    }

    
/**
     * Constructor for primary key
     
*/
    
public  BaseBlobTest (java.lang.Integer _id) {
        
this .setId(_id);
        initialize();
    }

    
protected   void  initialize () {}



    
/**
     * Return the unique identifier of this class
     * @hibernate.id
     *  generator-class="native"
     *  column="ID"
     
*/
    
public  java.lang.Integer getId () {
        
return  _id;
    }

    
/**
     * Set the unique identifier of this class
     * 
@param  _id the new ID
     
*/
    
public   void  setId (java.lang.Integer _id) {
        
this ._id  =  _id;
        
this .hashCode  =  Integer.MIN_VALUE;
    }


    
/**
     * Return the value associated with the column: MYBLOB
     
*/
    
public  java.sql.Blob getMyblob () {
        
return  _myblob;
    }

    
/**
     * Set the value related to the column: MYBLOB
     * 
@param  _myblob the MYBLOB value
     
*/
    
public   void  setMyblob (java.sql.Blob _myblob) {
        
this ._myblob  =  _myblob;
    }


    
public   boolean  equals (Object obj) {
        
if  ( null   ==  obj)  return   false ;
        
if  ( ! (obj  instanceof  old.BaseBlobTest))  return   false ;
        
else  {
            old.BaseBlobTest mObj 
=  (old.BaseBlobTest) obj;
            
if  ( null   ==   this .getId()  ||   null   ==  mObj.getId())  return   false ;
            
else   return  ( this .getId().equals(mObj.getId()));
        }
    }


    
public   int  hashCode () {
        
if  (Integer.MIN_VALUE  ==   this .hashCode) {
            
if  ( null   ==   this .getId())  return   super .hashCode();
            
else  {
                String hashStr 
=   this .getClass().getName()  +   " : "   +   this .getId().hashCode();
                
this .hashCode  =  hashStr.hashCode();
            }
        }
        
return   this .hashCode;
    }


    
public  String toString () {
        
return   super .toString();
    }

}


package  bo.base;

import  java.io.Serializable;


/**
 * This class has been automatically generated by Hibernate Synchronizer.
 * For more information or documentation, visit The Hibernate Synchronizer page
 * at 
http://www.binamics.com/hibernatesync  or contact Joe Hudson at joe@binamics.com.
 *
 * This is an object that contains data related to the BLOB_TEST table.
 * Do not modify this class because it will be overwritten if the configuration file
 * related to this class is modified.
 *
 * @hibernate.class
 *  table="BLOB_TEST"
 
*/
public   abstract   class  BaseBlobTest   implements  Serializable {

    
public   static  String PROP_MYBLOB  =   " Myblob " ;
    
public   static  String PROP_ID  =   " Id " ;


    
private   int  hashCode  =  Integer.MIN_VALUE;

    
//  primary key
     private  java.lang.Integer _id;

    
//  fields
     private   byte [] _myblob;


    
//  constructors
     public  BaseBlobTest () {
        initialize();
    }

    
/**
     * Constructor for primary key
     
*/
    
public  BaseBlobTest (java.lang.Integer _id) {
        
this .setId(_id);
        initialize();
    }

    
protected   void  initialize () {}



    
/**
     * Return the unique identifier of this class
     * @hibernate.id
     *  generator-class="native"
     *  column="ID"
     
*/
    
public  java.lang.Integer getId () {
        
return  _id;
    }

    
/**
     * Set the unique identifier of this class
     * 
@param  _id the new ID
     
*/
    
public   void  setId (java.lang.Integer _id) {
        
this ._id  =  _id;
        
this .hashCode  =  Integer.MIN_VALUE;
    }


    
/**
     * Return the value associated with the column: MYBLOB
     
*/
    
public   byte [] getMyblob () {
        
return  _myblob;
    }

    
/**
     * Set the value related to the column: MYBLOB
     * 
@param  _myblob the MYBLOB value
     
*/
    
public   void  setMyblob ( byte [] _myblob) {
        
this ._myblob  =  _myblob;
    }


    
public   boolean  equals (Object obj) {
        
if  ( null   ==  obj)  return   false ;
        
if  ( ! (obj  instanceof  bo.base.BaseBlobTest))  return   false ;
        
else  {
            bo.base.BaseBlobTest mObj 
=  (bo.base.BaseBlobTest) obj;
            
if  ( null   ==   this .getId()  ||   null   ==  mObj.getId())  return   false ;
            
else   return  ( this .getId().equals(mObj.getId()));
        }
    }


    
public   int  hashCode () {
        
if  (Integer.MIN_VALUE  ==   this .hashCode) {
            
if  ( null   ==   this .getId())  return   super .hashCode();
            
else  {
                String hashStr 
=   this .getClass().getName()  +   " : "   +   this .getId().hashCode();
                
this .hashCode  =  hashStr.hashCode();
            }
        }
        
return   this .hashCode;
    }


    
public  String toString () {
        
return   super .toString();
    }

}

 

package  old;


/**
 * This is the object class that relates to the blob_test table.
 * Any customizations belong here.
 
*/
public   class  BlobTest  extends  BaseBlobTest {

/* [CONSTRUCTOR MARKER BEGIN] */
    
public  BlobTest () {
        
super ();
    }

    
/**
     * Constructor for primary key
     
*/
    
public  BlobTest (java.lang.Integer _id) {
        
super (_id);
    }
/* [CONSTRUCTOR MARKER END] */
}


如果还有什么问题,请留言。(2007-10-11 by rosen jiang)

请注意!引用、转贴本文应注明原作者:Rosen Jiang 以及出处: http://www.blogjava.net/rosen

posted on 2005-08-12 15:06 Rosen 阅读(10361) 评论(8)  编辑  收藏 所属分类: O/R Mapping

评论

# re: Hibernate、iBATIS 与 BLOB 2006-05-15 11:40 yangzhihuan
请问,如果是iBATIS SQL Maps 与 SQL Server BLOB ,那么 <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>

这里应该怎么样配置呢??
只是使用java.sql.blob类就成了么???  回复  更多评论
  

# re: Hibernate、iBATIS 与 BLOB 2006-05-15 21:31 Rosen
yangzhihuan 你好,BlobTest 对象所包含的 myblob 属性是字节数组类型的,具体可在本文中找到,这部分还是写得很仔细了。由于本文是去年初撰写的,不知道现在最新的 iBatis 是否在处理 LOB 方面有所进步。  回复  更多评论
  

# re: Hibernate、iBATIS 与 BLOB 2006-12-07 16:31 jiniwang
非常感谢,但是其中有一些问题,ibatis 在 insert 的时候,如果数据量过大就会报错,超过2000大小。
你可以尝试一下,如果有解决办法,请通知我 jini_wang@hotmail.com  回复  更多评论
  

# re: Hibernate、iBATIS 与 BLOB 2006-12-08 00:53 Rosen
@jiniwang
:) 想不到这篇 05 年初的文章还在为大家服务,我很高兴。超过 2K 的问题请换数据库驱动,因为我在测试 HB/Oracle 的时候出现过这种情况(本文中也提到了有 4K 限制)。另外,我记得当时测试的时候我是存储的一张照片,大约 600K,所以应该不是代码或 iBATIS 自身的问题。
  回复  更多评论
  

# re: Hibernate、iBATIS 与 BLOB[未登录] 2007-10-11 15:56 phoenix
请问大哥,你发表的关于Hibernate存取SQL server2000中Blob字段的程序中BlobTest何在?内容是什么,里面隐藏了Java流向Blob的转换过程,请不吝赐教!我的邮箱为:jiphoenixsoft@163.com,望看到后回复,谢谢!急!!!!!  回复  更多评论
  

# re: Hibernate、iBATIS 与 BLOB 2007-10-11 19:13 Rosen
@phoenix
我回去找找,然后发给你,顺便我也提交到本文中。   回复  更多评论
  

# re: Hibernate、iBATIS 与 BLOB 2011-07-08 22:03 陈思
怎么后面的几个类是一样的?就是BaseBlobTest两个一样啊,只是包不一样
我是新手最近遇到这个问题,不是很明白?  回复  更多评论
  

# re: Hibernate、iBATIS 与 BLOB 2011-07-08 22:33 陈思
明白了,唉,我好菜  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: