`
sunguanxing
  • 浏览: 1097419 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

iBATIS操作CLOB字段实战浅析

阅读更多
iBATIS操作CLOB字段的问题:在网上搜索发现有人遇到了相似的问题,但是情况不尽相同。现在把经验写出来,与大家分享。

环境:

JDK/JRE:1.5.0;Spring:1.2.7;iBATIS:2.1.7;Oracle:9.2.0.1;JDBC:OJDBC14_10g.jar

目标:

基于Spring提供的DBCP,使用iBATIS SQL Maps更新数据库的CLOB字段。

现象:


总是有少部分特定的数据没有更新,且并不是因为数据过长而失败,有时很短的数据也会失败。现象可以重现。原来的SQL的 Maps配置文件如下:

﹤update id="updateByFoodID" parameterClass="Food"﹥    update TB_FOOD      ﹤dynamic prepend="set"﹥        ﹤isNotNull prepend="," property="foodDesc"﹥          FOOD_DESC = #foodDesc#        ﹤/isNotNull﹥        ﹤isNotNull prepend="," property="foodImage"﹥          FOOD_IMAGE = #foodImage#        ﹤/isNotNull﹥      ﹤/dynamic﹥    where FOOD_ID = #foodID#  ﹤/update﹥ 


查看log4j的DEBUG输出,只有Preparing Statement、Executing Statement、和Parameters,并没有异常输出。

iBATIS操作CLOB字段初步分析原因,有如下6个:

1、首先还是怀疑有地方数据过长;

2、操作的长字符串是JSON格式的,并且数据内容可能包含‘?’、‘/’等特殊字符;

3、由于有多个程序同时使用该表,可能是事务隔离的原因;

4、LOB字段在Dynamic Mapped Statements中运行的问题;

5、这个版本的Spring对iBATIS的支持问题;

6、JDBC的版本问题。

iBATIS操作CLOB字段分别分析:

1、VARCHAR2类型的列最长为4000字节,VARCHAR2类型的PL/SQL变量最长为32767字节,操作的数据确实有可能超过64k,但程序中没有使用VARCHAR2变量存储数据,LOB类型的列更是可以存储4G的数据;

2、走查更新失败的字符串内容,没有发现特殊之处;

3、新建一张临时表,用以进行insert和update操作,发现并没有解决问题;

4、去掉动态部分,写最简单的SQL语句,也没有解决问题;

5、(暂时略过);

6、这个可能性比较小,一直都在用最新版本的JDBC。

网上有人提到3种办法,其中“第2种”,给SqlMapClientFactoryBean增加lobHandler属性,据称是指能工作在native的驱动方式下,经查Spring的API文档,并不准确,摘录文档如下:

While most databases are able to work with DefaultLobHandler, Oracle just accepts Blob/Clob instances created via its own proprietary BLOB/CLOB API, and additionally doesn't accept large streams for PreparedStatement's corresponding setter methods. Therefore, you need to use a strategy like this LobHandler implementation.

Needs to work on a native JDBC Connection, to be able to cast it to oracle.jdbc.OracleConnection. If you pass in Connections from a connection pool (the usual case in a J2EE environment), you need to set an appropriate NativeJdbcExtractor to allow for automatical retrieval of the underlying native JDBC Connection. LobHandler and NativeJdbcExtractor are separate concerns, therefore they are represented by separate strategy interfaces.

Coded via reflection to avoid dependencies on Oracle classes. Even reads in Oracle constants via reflection because of different Oracle drivers (classes12, ojdbc14) having different constant values! As this LobHandler initializes Oracle classes on instantiation, do not define this as eager-initializing singleton if you do not want to depend on the Oracle JAR being in the class path: use "lazy-init=true" to avoid this issue.

因此,修改Spring配置文件:

﹤bean id="jdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor" /﹥  ﹤bean id="oracleLobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler" lazy-init="true"﹥      ﹤property name="nativeJdbcExtractor"﹥﹤ref local="jdbcExtractor" /﹥﹤/property﹥  ﹤/bean﹥  ﹤bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"﹥      ﹤property name="configLocation" value="classpath:conf/sqlMapConfig.xml"﹥﹤/property﹥      ﹤property name="dataSource"﹥﹤ref local="aeqdsDataSource" /﹥﹤/property﹥      ﹤property name="lobHandler"﹥﹤ref local="oracleLobHandler" /﹥﹤/property﹥  ﹤/bean﹥ 


未果。

使用提到的“第3种”方法,这又有2种方式,第1种是全局性的,在SQL Maps配置文件中加入callback方法:



﹤typeHandler jdbcType="BLOB" javaType="[B" callback="org.  ringframework.orm.ibatis.support.BlobByteArrayTypeHandler" /﹥  ﹤typeHandler jdbcType="CLOB" javaType="java.lang.String"   llback="org.springframework.orm.ibatis.support.ClobStringTypeHandler" /﹥


第2种是在单个的属性上指定typeHandler,如果是select,就可以用:
﹤resultMap id="foodResult" class="Food"﹥    ﹤result property="foodId" column="FOOD_ID"/﹥    ﹤result property="foodDesc" column="FOOD_DESC" typeHandler="org.springframework.orm.ibatis.support.ClobStringTypeHandler"/﹥    ﹤result property="foodImage" column="FOOD_IMAGE" typeHandler="org.springframework.orm.ibatis.support.BlobByteArrayTypeHandler"/﹥  ﹤/resultMap﹥ 


如果是insert或update,就可以用
﹤update id="updateByFoodID" parameterClass="Food"﹥    
update TB_FOOD      
set FOOD_DESC = #foodDesc,handler=org.springframework.orm.ibatis.support.ClobStringTypeHandler#,FOOD_IMAGE = foodImage,handler=org.springframework.orm.ibatis.support.BlobByteArrayTypeHandler#      where FOOD_ID = #foodID#  
﹤/update﹥ 



加入这个callback或typeHandler方法后,iBATIS抱怨没见过这个标记,程序不能启动。把iBATIS升级为2.3.0,顺便也把Spring升级为2.0.2,正常启动。但是效果更差,所有数据均不能更新,且日志显示只进行了Prepare Statement,却没有执行。

死马当活马医:

﹤parameterMap id="updateByFoodIDPara" class="Food"﹥
    ﹤parameter property="foodDesc" jdbcType="CLOB" javaType="java.lang.String" /﹥
    ﹤parameter property="foodImage" jdbcType="BLOB" javaType="[B" /﹥
    ﹤parameter property="foodID" jdbcType="VARCHAR" javaType="java.lang.String" /﹥  
﹤/parameterMap﹥
  ﹤update id="updateByFoodID" parameterMap="updateByFoodIDPara"﹥    
update TB_FOOD      
set FOOD_DESC = ?, FOOD_IMAGE = ?      where FOOD_ID = ?  
﹤/update﹥ 


依旧未果。

使出杀手锏,把update封装在一个存储过程中(其中不需要特别的事务处理),然后将SQL Maps配置文件的对应内容简简单单的修改为:

﹤procedure id="updateByFoodID" parameterClass="Food"﹥
    {call pkg_xxx.sp_xxx (#foodID#, #foodDesc#, #foodImage#)} 
 ﹤/procedure﹥


OK!

iBATIS操作CLOB字段的问题还是要在实战中多多总结,希望这篇文章对你理解iBATIS操作CLOB字段有所帮助
分享到:
评论

相关推荐

    iBATIS操作Oracle CLOB数据

    4. **查询操作**:查询包含CLOB字段的记录时,iBATIS会自动处理CLOB的读取。但是,由于CLOB可能很大,所以在处理结果集时应谨慎,避免内存溢出。 5. **类型处理器**:iBATIS提供了一个`OracleClobHandler`,它可以...

    ibatis oracle clob

    在iBATIS中,我们需要特别关注如何正确地读取和写入CLOB字段。 首先,iBATIS(现在被称为MyBatis)是一个优秀的持久层框架,它允许开发者将SQL语句嵌入到Java代码中,以简化数据库操作。它通过XML或注解的方式配置...

    ibatis 读取oracle clob类型

    ibatis 读取oracle clob类型

    解决IBatis缓存动态字段问题

    在使用IBatis框架处理数据库操作时,可能会遇到动态数据表名、动态字段名的情况。这种情况下,由于IBatis的缓存机制,可能导致字段找不到的问题。具体表现为:当第一次查询某个表时,IBatis会将查询结果中的字段名...

    mybatis 对clob类型转换

    当你需要将一个字符串或者Reader对象插入到CLOB字段时,MyBatis默认可能无法正确处理。此时,你需要自定义一个TypeHandler来处理这种转换。创建一个实现`org.apache.ibatis.type.TypeHandler`接口的类,重写`...

    iBATIS教程之快速入门浅析

    iBATIS 是一款轻量级的Java持久层框架,它主要负责对象关系映射(Object-Relational Mapping,简称O/R Mapping),使得开发者可以将关注点集中在业务逻辑上,而无需过多地处理数据库操作的细节。与Hibernate等其他...

    iBatis iBatis in Action iBatis实战

    还在寻找iBatis的学习资料?那么iBatis作者编著的这本《iBatis in Action》是最好的选择了!至于下载资源则是原著引进中国之后出版的官方中文版,大大的方便大家阅读,学习!完整的资源是91.6M,格式为pdf。值得下载...

    ibatis in action ibatis实战 - 2

    ibatis实战中文版 一共2个文件 ibatis in action

    ibatis in action ibatis实战 中文版 - 1

    ibatis实战中文版 一共2个文件 ibatis in action

    iBATIS实战.pdf

    《iBATIS实战》是讲述iBATIS框架的权威著作。书中既详实地介绍了iBATIS的设计理念和基础知识,也讨论了动态SQL、高速缓存、DAD框架等高级主题,还讲解了iBATIS在实际开发中的应用。《iBATIS实战》的最后给出了一个...

    ibatis实战.part07

    ibatis实战.part07ibatis实战.part07ibatis实战.part07ibatis实战.part07ibatis实战.part07ibatis实战.part07ibatis实战.part07ibatis实战.part07ibatis实战.part07ibatis实战.part07ibatis实战.part07ibatis实战....

    ibatis实战.part09

    ibatis实战.part09ibatis实战.part09ibatis实战.part09ibatis实战.part09ibatis实战.part09ibatis实战.part09ibatis实战.part09ibatis实战.part09ibatis实战.part09ibatis实战.part09ibatis实战.part09ibatis实战....

    ibatis实战.part08

    ibatis实战.part08ibatis实战.part08ibatis实战.part08ibatis实战.part08ibatis实战.part08ibatis实战.part08ibatis实战.part08ibatis实战.part08ibatis实战.part08ibatis实战.part08ibatis实战.part08ibatis实战....

    iBATIS实战

    在iBATIS实战中,你将学习如何有效地利用iBATIS来处理数据库操作,包括但不限于以下知识点: 1. **安装与配置**:了解如何在项目中引入iBATIS框架,设置相关的依赖,并配置数据库连接。这通常涉及到pom.xml或build....

    ibatis实战

    iBATIS实战.part2.rar

    struts2+spring+ibatis项目实战

    在这个“Struts2+Spring+iBatis项目实战”中,我们将深入探讨这三个框架的核心概念、整合方式以及在实际项目中的应用。 首先,Struts2是一个基于MVC(Model-View-Controller)设计模式的开源Web应用程序框架,它...

    ibatis基本操作数据库

    总之,iBatis提供了一种灵活的数据库操作方式,通过与Java代码的紧密结合,解决了传统JDBC的繁琐和易错问题。了解并熟练掌握iBatis的基本操作和特性,对于提升Java项目的数据库访问能力具有重要意义。

    iBatis实战 中文版

    还在寻找iBatis的学习资料?那么iBatis作者编著的这本《iBatis in Action》是最好的选择了!至于下载资源则是原著引进中国之后出版的官方中文版,大大的方便大家阅读,学习!完整的资源是91.6M,格式为pdf。值得下载...

    iBatis实战and源代码.zip

    《iBatis实战and源代码.zip》这个压缩包包含了关于iBatis框架的实战经验和源代码,对于深入了解和学习iBatis有着极大的帮助。iBatis是一个优秀的持久层框架,它允许开发者将SQL语句与Java代码分离,提高了开发效率和...

    iBatis操作MySQL增删改查

    在IT领域,数据库管理和操作是不可或缺的部分,而iBatis作为一个优秀的持久层框架,与MySQL数据库结合使用,能实现高效且灵活的数据操作。本篇文章将深入探讨如何利用iBatis进行MySQL数据库的增删改查操作,同时提供...

Global site tag (gtag.js) - Google Analytics