`
耳东成陈
  • 浏览: 15337 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
社区版块
存档分类
最新评论

spring帮你处理lob类型的数据

 
阅读更多
LOB字段在处理二进制(BLOB)数、大文本(CLOB)时非常有用。无论什么数据库,Spring都能够很好的、一致的处理LOB字段。
为了操控LOB字段,Spring应用需要启动LobHandler继承链。

目前Spring内置了DefaultLobHandler和OracleLobHandler实现类。

通常除了Oracle数据库外,借助Spring内置的JDBC集成操作LOB字段时,开发者直接配置一DefaultLobHandler实例即可。



struts+spring+hibernate开发中blob字段映射完全解决手册- -

在使用struts+spring+hibernate的开发中,一般在oracle数据库中采用Blob字段或Clob字段来
存储二进制的图片或附件。
通过使用spring的usertype提供的处理lob类型的映射方法可以轻松的解决读写blob的问题。
参考如下:
=================================================================
rickyang 2006-04-20 12:33
Spring或Hibernate其实都提供了透明处理Clob的方法
只是个人觉得用Spring的做法比hibernate更透明一点(hibernate2.16);
具体做法为:
1.在sessionFactory中加入lobHandler的注射:

<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="lobHandler" ref="lobHandler"/>
        <property name="mappingResources">
                  <value>xxx.hbm.xml</value>
                  .....
         </property>
</bean>

2.定义这个lobHandler,值得注意的是这里有Oracle的版本区别:

<bean id="lobHandler" lazy-init="true"   class="org.springframework.jdbc.support.lob.OracleLobHandler">
        <property name="nativeJdbcExtractor">
            <ref bean="nativeJdbcExtractor"/>
        </property>
</bean>

<bean id="nativeJdbcExtractor" lazy-init="true"   class="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor"/>

因为Oracle9i处理Clob的方式和别的数据库很不一样,甚至与Oracle10g都不兼容,所以这里要用spring提供的SimpleNativeJdbcExtractor.如果使用Oracle10g的话,可以直接使用:

<bean id="lobHandler" lazy-init="true"  class="org.springframework.jdbc.support.lob.DefaultLobHandler"/>

对应的应该使用Oracle10g对应的JDBC驱动.

4.在领域对象的hbm中对应的Clob字段应该使用这样的定义:

<property name="context" column="context" type="org.springframework.orm.hibernate.support.ClobStringType" length="1048576000"/>

这里的length是字节了,不是长度哦,最大可以设到2G.对应的,该字段在领域对象中直接申明成String就可以了.当对这个字段写入长数据时直接调用其set方法就可以了,Spring会自己帮你做余下的处理,让你透明的处理Clob字段.

5.业务逻辑层对该字段的操作必须需要在有事务管理的方法中使用,否则会报:
java.lang.IllegalStateException: Active Spring transaction synchronization or active JTA transaction with 'jtaTransactionManager' on LocalSessionFactoryBean required 这个错误



=================================================================


遇到的问题:
1.由于附件表中有blob字段,在对blob的字段的读取中会导致把blob二进制流读出,如果数据量
大会导致内存溢出,何况blob仅仅在下载文件的时候才需要用到,这就需要对blob的字段进行延迟加载
参考hibernate的文档改成:
<property name="data" type="org.springframework.orm.hibernate3.support.BlobByteArrayType" lazy="true">
     <column name="DATA" />
  </property>
  但是在加载的时候并没有想像的那样进行延迟加载,而是直接加载了,参考了hibernate手册,其中描述了该问题:
======================================================================
  20.1.7. 使用延迟属性抓取(Using lazy property fetching)
Hibernate3对单独的属性支持延迟抓取,这项优化技术也被称为组抓取(fetch groups)。 请注意,该技术更多的属于市场特性。在实际应用中,优化行读取比优化列读取更重要。但是,仅载入类的部分属性在某些特定情况下会有用,例如在原有表中拥有几百列数据、数据模型无法改动的情况下。

可以在映射文件中对特定的属性设置lazy,定义该属性为延迟载入。

<class name="Document">
       <id name="id">
        <generator class="native"/>
    </id>
    <property name="name" not-null="true" length="50"/>
    <property name="summary" not-null="true" length="200" lazy="true"/>
    <property name="text" not-null="true" length="2000" lazy="true"/>
</class>
属性的延迟载入要求在其代码构建时加入二进制指示指令(bytecode instrumentation),如果你的持久类代码中未含有这些指令, Hibernate将会忽略这些属性的延迟设置,仍然将其直接载入。

你可以在Ant的Task中,进行如下定义,对持久类代码加入“二进制指令。”

<target name="instrument" depends="compile">
    <taskdef name="instrument" classname="org.hibernate.tool.instrument.InstrumentTask">
        <classpath path="${jar.path}"/>
        <classpath path="${classes.dir}"/>
        <classpath refid="lib.class.path"/>
    </taskdef>

    <instrument verbose="true">
        <fileset dir="${testclasses.dir}/org/hibernate/auction/model">
            <include name="*.class"/>
        </fileset>
    </instrument>
</target>
还有一种可以优化的方法,它使用HQL或条件查询的投影(projection)特性,可以避免读取非必要的列, 这一点至少对只读事务是非常有用的。它无需在代码构建时“二进制指令”处理,因此是一个更加值得选择的解决方法。

有时你需要在HQL中通过抓取所有属性,强行抓取所有内容。

======================================================================
对其中的自解码增强一直也没有搞的太明白,导致了更多的郁闷。放弃了使用自解码增强的方法。
而考虑了使用hql来只抓取其中的字段.如下面的HQL:
select new DayMonth(recordId,fileName,fileSize) from DayMonth where .....
这样做必须在对应的pojo中提供你需要的构造方法。这样在抓取该对象的时候就过滤的Blob字段。
虽然这样仅仅勉强解决了问题,但是在使用spring的HibernateTemplate中提供的findById,find等方法的时候还是
无法解决,除非都用HQL,这样也太蹩脚了。

问题2,如何做能够把一个表映射成2个类,其中的id和blob字段单独映射,其他字段和id映射成一个类。这样可以建立关联
并且可以避免在不需要的时候不读blob字段。
网上了很久,只有一些支离破碎的东西,没有明白讲解如何配置,特别是这样配置后他们的关联关系如何维护。
自己尝试采用one-to-one来配置同一个表对应2个类的关系,但配置中总启动报错或不能延迟加载,而下面的帖子给了我提示。
===================================
javapassion 发表于 2006-7-3 16:20:29

[引用]众所周知,到了Hibernate3.0以后,关联关系的对象默认都是使用延迟加载,例如<one-to-many>时.但我在映射<one-to-one>,<many-to-one>关系时指定了lazy="true",但是在查询对象时,我只想查询一个对象,仍然会把这个对象所关联的<one-to-one>,<many-to-one>对象一起查询出来,这样造成了极大的性能浪费.在不指定lazy属性时,<many-to-one>所关联的对象反而会延迟加载,这让我大为困惑,还以为是Hibernate的bug.
在网上查找资料,说在为了延迟加载<one-to-one>,<many-to-one>所关联的对象,需要设置被关联的对象<class name="" lazy="true">,我也这样做了,但是仍然没有效果.
仔细阅读了Hibernate的手册,才发现原来要延迟加载<one-to-one>,<many-to-one>所关联的对象时,除了要指定lazy="true"外,还需要运行期字节码增强,而我省去了这一步,所以延迟加载没有效果.同时还发现在默认情况下,<one-to-one>,<many-to-one>的lazy属性是"proxy"而不是"true"!因此如果直接采用lazy的默认值,是可以延迟加载的.
总结一下:
<many-to-one>默认的属性是lazy="proxy",此时默认是会延迟加载的.在指定了lazy="true"之后,必须要经过运行期字节码增加,延迟加载才有效果.
而<one-to-one>相对要复杂一点,延迟加载还要受到constrained属性的限制.constrained="false"时表明实体和被关联到的实体的约束不是强制的,即存在一个实体时,它通过<one-to-one>关联的实体可能存在,也可能不存在,这时在查询实体时,Hibernate总会发起一次查询检查<one-to-one>所关联的实体是否存在,而这时已经可以把one-to-one关联的实体查询出来了,因此在<one-to-one>关系中,如果constrained="false",总是会立即加载关联到的实体.
如果当constrained="true",且lazy="proxy"(默认),是可以延迟加载的.
如果当constrained="true",且lazy="true"时,需要经过运行期字节码增加,延迟加载才会奏效.

=========================================
最终基本映射成功:其中的2个类一个是:dayMonth 一个是blobData。映射同一个表:YXGL_DAY_MONTH
*******************************************************************************
<hibernate-mapping>
    <class name="cn.com.sgcc.run.daymonth.DayMonth" table="YXGL_DAY_MONTH" schema="SGCC" >
        <id name="recordId" type="long">
            <column name="RECORD_ID" precision="22" scale="0" />
            <generator class="sequence" >
      <param name="sequence">SEQ_YXGL_DAY_MONTH_ID</param>
   </generator>
        </id>
        <property name="scopeType" type="long">
            <column name="SCOPE_TYPE" precision="5" scale="0" not-null="true" />
        </property>
        <property name="projectType" type="long">
            <column name="PROJECT_TYPE" precision="5" scale="0" not-null="true" />
        </property>
        <property name="projectId" type="string">
            <column name="PROJECT_ID" length="10" not-null="true" />
        </property>
        <property name="fileName" type="string">
            <column name="FILE_NAME" length="100" />
        </property>
        <property name="fileType" type="string">
            <column name="FILE_TYPE" length="15" />
        </property>
      <!--   <property name="data" type="org.springframework.orm.hibernate3.support.BlobByteArrayType" lazy="true">
            <column name="DATA" />
        </property>
        -->
        <property name="fileSize" type="long">
            <column name="FILE_SIZE" precision="22" scale="0" />
        </property>
        <property name="uploadTime" type="timestamp" insert="false" update="false">
            <column name="UPLOAD_TIME" length="7" />
        </property>
        <property name="filePath" type="string">
            <column name="FILE_PATH" length="400" />
        </property>
        <property name="deptId" type="long" update="false">
            <column name="DEPT_ID" precision="22" scale="0" />
        </property>
        <property name="remark" type="string">
            <column name="REMARK" length="400" />
        </property>
   <property name="reportDate" type="timestamp">
            <column name="REPORT_DATE" length="7" />
        </property>
  <property name="userId" type="long" update="false">
            <column name="USER_ID"  />
        </property>
        <one-to-one name="blobData" constrained="true"></one-to-one>
    </class>
  
     <class name="cn.com.sgcc.util.data.BlobData" table="YXGL_DAY_MONTH" schema="SGCC" >
      <id name="recordId" type="long">
            <column name="RECORD_ID" precision="22" scale="0" />
            <generator class="foreign" >
      <param name="property">dayMonth</param>
   </generator>
        </id>
       <property name="data" type="org.springframework.orm.hibernate3.support.BlobByteArrayType" >
            <column name="DATA" />
        </property>
        <one-to-one name="dayMonth" constrained="true" lazy="false"></one-to-one>
     </class>
</hibernate-mapping>
*******************************************************************************
但是这样做,对于saveOrUpdate对象DayMonth的时候不能级联BlobData,因为他们是同一张表会导致2次插入,
只能在save完DayMonth的时候,把DayMonth的主键id赋值给BlobData,然后再save对象BlobData,这样它做的
是更新操作,正好更新了字段blob。在要下载附件的时候,仅仅load对象BlobData就可以了。
参考代码:
insert操作
dayMonthService.saveObject(dayMonth);
//   System.out.println("dayMonth--id==="+dayMonth.getRecordId());
   dayMonth.getBlobData().setRecordId(dayMonth.getRecordId());
   dayMonthService.saveObject(dayMonth.getBlobData());
update操作:
dayMonthService.saveObject(dayMonth);
//   System.out.println("dayMonth--id==="+dayMonth.getRecordId());
   dayMonth.getBlobData().setRecordId(dayMonth.getRecordId());
   dayMonthService.saveObject(dayMonth.getBlobData());
 
到此为止,基本上解决了该问题。尽管不是很完美,但基本上能满足要求了。。。。


特别注意:oracle9,oracle10g,hibernate2,hibernate3写blob字段的区别
分享到:
评论

相关推荐

    简单易行:Spring中操作LOB字段案例

    在Spring框架中,LOB(Large Object)字段通常用于存储大数据,如BLOB(Binary Large Object)用于二进制数据,如图片或文档,CLOB(Character Large Object)用于字符数据,如长文本。本篇文章将深入探讨如何在...

    Spring+Hibernate处理Oracle lob字段(一)

    在Oracle数据库中,LOB字段主要有BLOB(Binary Large Object)和CLOB(Character Large Object)两种类型,分别用于存储二进制和字符数据。处理这些字段时,我们需要配置Hibernate的实体类和映射文件。 在实体类中...

    用PHP操纵Oracle的LOB类型的数据

    由于Oracle将LOB视为特殊数据类型,因此在插入、读取和查询时需要采用特定的方法。以下是使用PHP的OCI函数进行操作的步骤: 1. **插入LOB数据**: - 首先,不能直接在INSERT语句中插入LOB值,而是需要先创建一个空...

    ODI LOB 类型KM

    在Oracle数据库中,LOB是一种特殊的数据类型,用于存储大型的二进制或文本数据,如图片、视频、文档或大段文本。LOB分为四种主要类型:BLOB(Binary Large Object)用于存储二进制数据,CLOB(Character Large ...

    SQL Server存储LOB数据的策略与方法.pdf

    LOB数据类型通常是指存储在数据库中非常大的二进制或者字符型数据,例如文档、图表和图像文件。这些数据的特点是单个对象的大小经常超过数据库系统中常见的8KB的限制。在SQL Server中,LOB数据可以以text、ntext或...

    本文档主要介绍如何对LOB字段进行处理

    为了解决这一问题,Oracle数据库引入了LOB(Large Objects,大对象)数据类型来存储大量二进制和文本数据。本文旨在详细介绍如何在Oracle数据库中使用和维护LOB数据类型。 #### LOB概述 在Oracle数据库中,LOB是一...

    java存lob数据到sybase数据库

    通过spring存blob和clob数据到sybase数据库中,压缩包里包含了三种方式,(1)spring+hibernate,切面事务(aop),存lob数据,(2)spring+hibernate存lob数据,(3)spring+jdbc存lob数据。

    ORACLE LOB大对象处理

    Oracle数据库中的LOB(Large Object)类型是用来存储大量数据的,如文本、图像、音频或视频等。LOBs分为四种类型:BLOB(Binary Large Object)用于二进制数据,CLOB(Character Large Object)用于字符数据,NCLOB...

    Oracle数据库中LOB的调优.pdf

    在Oracle数据库中,LOB数据类型的存储和优化是非常重要的,因为LOB数据类型占用的存储空间较大,且其读写操作也较慢。 在创建包含LOB字段的表时,Oracle将同时创建两个段来容纳指定的列,这两个段分别为LOBINDEX和...

    cx_Oracle.LOB类型数据转化成字典

    1. cx_Oracle.LOB类型数据的处理:通过读取并拼接LOB对象转化为字符串,然后解析为字典。 2. 数据库操作封装:`dao`函数接受SQL语句,根据其类型执行查询或修改操作。 3. 单例模式:`Conn`类使用单例模式确保全局...

    DB2 LOB 详解

    在处理LOB数据时,数据库管理员需要掌握一些系统基础知识,例如数据类型的能力和页面大小限制。DB2作为关系数据库管理系统(RDBMS),它支持非关系型数据结构,如LOB和XML。LOB数据类型允许在单个列中存储比传统数据...

    Oracle LOB字段处理工具

    Oracle数据库系统中,LOB(Large Object)字段是用来存储大量数据的类型,如图像、音频、视频或大型文本文件。在数据库操作中,LOB字段的处理往往比常规的行数据更为复杂,因为它涉及到大块的数据读取、写入和管理。...

    oracle dbms_lob

    LOBs是Oracle提供的一种数据类型,用于存储大量数据,如文本、图像、音频或视频文件等。这个包包含了各种过程和函数,用于创建、读取、写入、修改和删除LOB数据。 `DBMS_LOB`包中的主要功能包括: 1. **创建LOB**...

    Oracle Lob Performance Guidelines

    在数据库管理与优化领域,Oracle LOB 类型因其存储大量文本或二进制数据的能力而被广泛使用。然而,正确地使用和优化 LOB 可以显著提升数据库应用的整体性能。本文档将基于提供的描述和部分内容,详细介绍如何针对 ...

    ORACLELOB大对象处理[定义].pdf

    Oracle中的LOB(Large Object)是用于存储大量非结构化数据的数据类型...总之,Oracle的LOB数据类型为存储和管理大型非结构化数据提供了强大支持,通过合理的表设计和使用`DBMS_LOB`包,可以高效地处理这些大数据对象。

    OCI_LOB样例程序

    在Oracle数据库中,LOB(Large Object)是用来存储大量数据的数据类型,如文本、图像或音频文件。OCI(Oracle Call Interface)是Oracle提供的C语言接口,用于开发与Oracle数据库交互的应用程序。`OCI_LOB`样例程序...

    lob字段数据删除空间测试.txt

    测试oracle数据库中,lob字段在不同参数条件下,删除数据后占用空间的情况。 测试1 测试disable storage in row下的lob字段 测试2 测试非disable storage in row模式下 该模式为默认模式,既小于4k的数据不会存在lob...

    使用JDBC数据接口存取Oracle LOB(大对象).pdf

    《使用JDBC数据接口存取Oracle LOB(大对象)》这篇文章主要探讨了如何通过Java数据库连接(JDBC)接口来处理Oracle数据库中的大对象(LOB)数据类型,特别是BLOB和CLOB。Oracle数据库利用LOB技术有效地管理和存储非...

Global site tag (gtag.js) - Google Analytics