`
魔力猫咪
  • 浏览: 106641 次
  • 来自: 北京
社区版块
存档分类
最新评论

Hibernate 中Blob字段的使用

阅读更多
猫咪以前发了一个关于在Hibernate中使用Clob字段的文章。可以做到以String的方式,直接把大量文字写入字段中而不用进行复杂编码。现在猫咪把使用Blob的方法也写出来。猫咪很懒,所以很久没有更新博客了。大家多多包涵!
下面是猫咪的例子(仍然使用Oracle,请确保使用最新的JDBC驱动)
首先建立一个数据库表

create table textblob (tid number(38,0),lob blob)

然后建立对应的Java对象

public class testblob {
         private long id;
         private byte[] lob;
         //set和get方法略...
    }

 最后是Hibernate配置和映射文件。

<hibernate-configuration>
        <session-factory>
        <property name="connection.driver_class">
            oracle.jdbc.driver.OracleDriver
            </property>
            <property name="connection.url">
            jdbc:oracle:thin:@xxx.xxx.xxx.xxx:1521:orcl
            </property>
            <property name="connection.useUnicode">true</property>
            <property name="connection.characterEncoding">UTF-8</property>
            <property name="connection.username">xxxxxx</property>
            <property name="connection.password">xxxxxx</property>
            <property name="hibernate.connection.provider_class">
            org.hibernate.connection.C3P0ConnectionProvider
            </property>
            <property name="hibernate.c3p0.max_size">20</property>
            <property name="hibernate.c3p0.min_size">5</property>
            <property name="hibernate.c3p0.timeout">120</property>
            <property name="hibernate.c3p0.max_statements">100</property>
            <property name="hibernate.c3p0.idle_test_period">120</property>
            <property name="hibernate.c3p0.acquire_increment">2</property>
            <property name="hibernate.connection.SetBigStringTryClob">
            true
            </property>
            <property name="hibernate.jdbc.use_streams_for_binary">
            true
            </property>
            <property name="dialect">
            org.hibernate.dialect.Oracle9Dialect
            </property>
            <property name="hibernate.show_sql">true</property>
            <property name="hibernate.transaction.factory_class">
            org.hibernate.transaction.JDBCTransactionFactory
            </property>

      <mapping resource="org/Miao/testblob.hbm.xml" />
         </session-factory>
     </hibernate-configuration>

 

 

注意配置文件中“hibernate.jdbc.use_streams_for_binary”这个部分。这是Oracle必须添加的属性。其它配置没有什么特别的。SQL Server不需要这个属性。同时配置文件配置了一个C3P0数据库连接池。

 

映射文件如下:

<hibernate-mapping package="org.Miao">
        <class name="testblob" table="tblob">
            <id name="id" column="tid">
               <generator class="native"></generator>
            </id>
        <property name="lob" column="tlob" type="binary">

    </property>
     </class>
</hibernate-mapping>

 

然后就可以测试一下了。写一个运行的测试类Run.class。

public class run {
      public static void main(String[] args) {
         Configuration configuration = new Configuration();
         configuration.configure();
         SessionFactory sessionFactory = configuration.buildSessionFactory();
         Session session = sessionFactory.openSession();
         File f = new File("d:/f.exe");
         byte[] tmp = new byte[(int) f.length()];
         try {
               FileInputStream fi = new FileInputStream(f);
               fi.read(tmp);
          } catch (FileNotFoundException e1) {
          e1.printStackTrace();
          } catch (IOException e) {
          e.printStackTrace();
          }
          testblob test = new testblob();
          test.setId(5);
          test.setLob(tmp);
          Transaction t = session.beginTransaction();
          try {
              session.saveOrUpdate(test);
              t.commit();
          } catch (HibernateException e) {
             e.printStackTrace();
             t.rollback();
          } finally {
             session.close();
          }
    }

}

 

现在进入数据库的话,可以看到数据库记录中已经增加了一条,文件已经被保存到数据库里了。但是,这么做有一个很大的问题,那就是内存。在Eclipse+WTP的环境下,加入的文件稍微大一点,就会造成OutofMemony异常。因为用这种方法存入数据库,需要把文件全部读入内存才可以。文件一大,就会造成内存溢出,即使把JVM使用的内存调大,保存大文件也是非常慢的。我的调试环境,存一个10M的文件,单用户Tomcat(内存调整到256-512M)跑,Oracle10g又是远程,需要好几分钟。多用户条件下,性能可想而知。而且,一旦多用户同时保存或同时读取大文件,立马会造成内存占用暴增,最后溢出。所以,使用这种方式处理Blob,一定要注意,不要保存大文件,我觉得最好不要超过1M。

分享到:
评论
8 楼 魔力猫咪 2008-02-02  
我去卓越网看了一下你说的那本书的介绍。在章节目录中有“移植到Hibernate 3 ”这么一章。虽然在简介里没有说明介绍的Hibernate的版本,但是通过这章,可以很明显看出介绍的是Hibernate2。
Hibernate2到Hibernate3可以说是一个飞跃。所以不要把Hibernate2的实践直接套用在3上。请在写代码的时候,自己先在机器上运行一下。
7 楼 魔力猫咪 2008-02-02  
<div class='quote_title'>dmewy 写道</div><div class='quote_div'>根据深入浅出hibernate这本书. <br/>把你的实现修改一下. <br/><p> </p><pre name='code' class='xml'>&lt;property name="lob" column="tlob" type="java.sql.Blob"&gt;  </pre><p>然后要在hibernate配置文件中加入一句话:</p><pre name='code' class='xml'>&lt;property name="hibernate.jdbc.batch_size"&gt;0&lt;/property&gt; 
</pre><p> </p><p>因为Oracle JBDC不允许流操作以批量方式执行.</p><p>然后</p><p>测试类里面可以写:</p><pre name='code' class='java'>testblob test = new testblob();  
test.setId(5);  
test.setLob(Hibernate.createBlob(new byte[1])); 
Transaction t = session.beginTransaction();  
session.save(test);  
//调用flush方法,强制Hibernate立即执行 sql 语句
session.flush();
//通过refresh方法,强制Hibernate执行select for update
session.refresh(test,LockMode.UPGRADE);
//向Blob写入实际内容
oracle.sql.BLOB blob=(oracle.sql.BLOB)test.getLob();
OutPutStream out =blob.getBinaryOutputStream();
FileInputStream imgis=new FileInputStream("xx.jpg");
byte[] buf = new byte[10240];//10k缓存
int len=0;
while((len=imgis.read(buf))&gt;0){
out.write(buf,0,len);
}
imgis.close();
out.close();
session.save(test);
t.comit();

</pre><p> </p></div><p><br/>很可惜。这么写是错误的。</p><p>Hibernate.createBlob(new byte[1]))生成的BLOB根本无法转化成Oracle的BLOB。它们虽然都继承自BLOB,但是不能强行转换。这种写法只适用于Hibernate2,3以后是不能用的。如果不想用我的方法,那么只能自己写Hibernate类型或使用Spring提供的类型。但是这样一来增加了难度或和Spring紧耦合了。</p><p>还有,你的写法造成了代码和数据库的紧耦合。也就是说如果更换数据库,那么必须修改代码。同时在Hibernate配置中关闭了批处理,造成系统整个性能下降。可以说是得不偿失。</p><p>深入浅出Hibernate我记得应该是一本比较早期的Hibernate参考书,上面的很多东西已经不适用于最新的Hibernate版本了。</p>
6 楼 dmewy 2008-02-02  
根据深入浅出hibernate这本书. <br/>把你的实现修改一下. <br/><p> </p><pre name='code' class='xml'>&lt;property name="lob" column="tlob" type="java.sql.Blob"&gt;  </pre><p>然后要在hibernate配置文件中加入一句话:</p><pre name='code' class='xml'>&lt;property name="hibernate.jdbc.batch_size"&gt;0&lt;/property&gt; 
</pre><p> </p><p>因为Oracle JBDC不允许流操作以批量方式执行.</p><p>然后</p><p>测试类里面可以写:</p><pre name='code' class='java'>testblob test = new testblob();  
test.setId(5);  
test.setLob(Hibernate.createBlob(new byte[1])); 
Transaction t = session.beginTransaction();  
session.save(test);  
//调用flush方法,强制Hibernate立即执行 sql 语句
session.flush();
//通过refresh方法,强制Hibernate执行select for update
session.refresh(test,LockMode.UPGRADE);
//向Blob写入实际内容
oracle.sql.BLOB blob=(oracle.sql.BLOB)test.getLob();
OutPutStream out =blob.getBinaryOutputStream();
FileInputStream imgis=new FileInputStream("xx.jpg");
byte[] buf = new byte[10240];//10k缓存
int len=0;
while((len=imgis.read(buf))&gt;0){
out.write(buf,0,len);
}
imgis.close();
out.close();
session.save(test);
t.comit();

</pre><p> </p>
5 楼 zlt820107 2008-01-22  
新手,学习了
4 楼 魔力猫咪 2008-01-22  
rainy 写道
blob可以放到InputStream,需要时再去读

但是我没找到Hibernate直接映射能这么做的方法。能否给个例子?
3 楼 rainy 2008-01-22  
blob可以放到InputStream,需要时再去读
2 楼 魔力猫咪 2008-01-21  
我觉得无论如何,都最好不要往BLOB中存放大文件。毕竟从数据库中读大文件,是非常缓慢的(想想几百兆的文件从数据库一点一点都到服务器,然后再一点一点response出去)。我觉得大文件还是以文件的方式存放比较好。而且传输的时候,直接给出链接就够了。剩下的事情,由操作系统自己往网卡发就是了。可以大大减轻压力。
Hibernate对JDBC做了很多封装。所以我们从Hibernate得到的CLOB和BLOB其实都是Hibernate自己实现的。而像Oracle之类的一些数据库,他们如果要操作BLOB、CLOB,需要用他们自己实现的对象。而Hibernate中得到的大字段对象是无法转化成数据库特有的大字段对象的。如果非要这么做,只能单独写纯JDBC。那么JDBC的获得、代码耦合、事务难以控制等问题都来了。
至于缓冲,我不知道数据库驱动保存BLOB能否自动缓冲。但是,缺省情况下,是要先把整个文件都读到内存中的。这个可无法缓冲。所以,如果一个人读入一个10M的文件,那么这10M在存入数据库前,都要保留在内存中,100个人的话,就要1G。如果更大,那么内存需要更是恐怖。
1 楼 jomper 2008-01-21  
不知道lz 有没有感觉
"直接把大量文字写入字段中而不用进行复杂编码"
"所以,使用这种方式处理Blob,一定要注意,不要保存大文件,我觉得最好不要超过1M。"

似乎这个方案还有待斟酌?

是否可以 buffer byte[]

相关推荐

    Hibernate读取blob字段

    本篇文章将深入探讨如何使用Hibernate读取数据库中的Blob字段,以及涉及到的相关知识点。 首先,我们需要理解Blob类型在数据库中的含义。Blob是Binary Large Object的缩写,它是一种可以存储大量二进制数据的数据...

    jdbc+hibernate存取blob字段

    本篇将详细介绍如何使用JDBC(Java Database Connectivity)与Hibernate框架来操作Oracle数据库中的BLOB字段。 首先,Oracle数据库的BLOB字段提供了对大对象的高效存储,它的性能优于LONG字段,尤其适合存储大容量...

    hibernate对Blob类型字段进行数据添加.txt

    在 Java 应用开发中,尤其是使用 ORM 框架如 Hibernate 进行持久化层开发时,如何高效地处理 BLOB 类型字段成为了一个关键问题。 本文档将详细介绍如何使用 Hibernate 对 Blob 类型字段进行数据添加的过程,并通过...

    Hibernate操作Oarcle中Clob、Blob字段小结

    - 在Hibernate的实体类中,我们需要为Clob和Blob字段定义对应的属性,并使用`@Lob`注解来标记它们。例如: ```java @Lob private Clob largeText; @Lob private Blob binaryData; ``` - 对于Clob,可以使用`...

    Hibernate对BLOB CLOB操作

    首先,我们来看一下如何在数据库中创建包含BLOB和CLOB字段的表。例如,以下SQL语句创建了一个名为`users`的表,其中`uids`为主键,`img`为BLOB类型,`txt`为CLOB类型: ```sql CREATE TABLE users ( uids int ...

    关于在Hibernate中对于Clob,Blob字段的处理方法

    在Hibernate的实体类中,我们需要为Clob和Blob字段定义对应的属性,并在映射文件(如.hbm.xml)或使用注解进行配置。例如,使用注解的方式: ```java @Lob private Clob largeText; @Lob private Blob binary...

    JDBC+Hibernate将Blob数据写入Oracle

    在IT领域,尤其是在数据库...总之,无论是使用JDBC还是Hibernate,正确处理Oracle中的BLOB字段都是至关重要的,尤其是在处理大量二进制数据的应用场景下。掌握上述流程和技巧,能够有效提升数据操作的效率和安全性。

    hibernate保存blob,clob对象

    接下来,我们需要在映射文件(.hbm.xml)中配置Blob字段,比如: ```xml &lt;hibernate-mapping&gt; &lt;!-- Blob类型的映射 --&gt; &lt;column name="PICTURE" length="1000000" sql-type="BLOB"/&gt; &lt;/hibernate...

    使用Hibernaet存储MYSQL表中BLOB字段的问题

    通过理解这些问题和解决方案,我们可以更有效地在Hibernate中管理和操作MySQL的BLOB字段。同时,持续关注官方文档和社区更新,以获取最新的最佳实践和修复。在实际项目中,结合适当的测试和性能监控,可以帮助我们更...

    hibernate struts处理mysql数据库blob字段实例

    本实例主要探讨如何利用Hibernate和Struts框架来处理MySQL数据库中的BLOB字段,实现文件的上传与下载功能。 **一、Hibernate框架** Hibernate是一个强大的Java持久化框架,它简化了数据库操作,提供了对象关系映射...

    使用JDBC和Hibernate来写入Blob型数据到Oracle中

    以下是使用JDBC直接操作Blob字段的步骤: 1. 注册并加载Oracle的JDBC驱动: ```java DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); ``` 2. 创建数据库连接: ```java Connection ...

    Hibernate对Blob,Clob的操作

    在Java Web开发中,...本文将详细介绍如何在Hibernate中操作Blob和Clob字段,实现数据的存储与读取。 首先,我们需要在Hibernate映射文件(.hbm.xml)中定义Blob和Clob字段。对于Blob,可以这样声明: ```xml ...

    hibernate Blob、Clob字段的映射的例子

    hibernate Blob、Clob字段的映射的例子.数据库mysql,数据库放在文件夹里面,例子的说明文章在我的csdn blog: http://blog.csdn.net/zhengcandan

    oracle+hibernate 处理blob +uploadify实例

    综上所述,这个实例展示了如何在Oracle数据库中使用Hibernate处理Blob数据,结合Uploadify实现文件上传。这种解决方案不仅适用于Oracle,理论上也适用于其他支持Blob类型的数据库,如MySQL和MSSQLServer。了解这些...

    使用hibernate对oracle读取blob

    在实体类中,你可以定义一个Blob类型的属性来表示数据库中的Blob字段: ```java @Entity public class MediaEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Lob ...

    spring+hibernate 解决大字段(clob)

    在Hibernate的`SessionFactory`配置中,需要指定`lobHandler` Bean来处理CLOB和BLOB字段: ```xml &lt;bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"&gt; ...

Global site tag (gtag.js) - Google Analytics