仅可以为插入 LONG 列的 LONG 值赋值 CLOB的解决方案

最近在做一个项目,原先是用Mysql数据库开发的,现在因客户要求,迁移到oracle。

开发的环境是,wsi(webwork+spring+ibaits).

数据库的字符集是UTF-8.

 

迁移过程中,碰到了这样一个问题,向一个表中执行update和insert操作时,类型为CLOB列的就出现异常

异常为:

仅可以为插入 LONG 列的 LONG 值赋值 CLOB

............

当时上网查了,有很多人也碰到了相同的问题,总体而言有两种解决方式,

第一种是驱动版本过低。

第二种是修改hibernate的配置文件,当时,前提是你开发的持久层必须是hibernate。

我从oracle官方网站下了一个最新的JDBC驱动(通过附件上传了),运行还是报哪个错误。没有效果

而第二种方法,对于我而言,是肯定行不通的。

 

网上有部分人说,值长度在2000-4000之间会出现异常,

可是,我的不同,

我的是值的长度在1000-2000之间会出现异常,稍短或长都没问题。

 

在这里说明一下,肯定不会是因为长度限制的问题,因为CLOB在ORACLE里面,所输入的可达4G。

对于LONG,这个类型我没用过,在ORACLE里面也不建议用。是一个已经被废弃了的类型。

 

最后我的解决方法是,在视图层,对所输入的进行判断,把少了的用空格不上,在jsp中,四个空格等于一个字符的长度。

让其长度超过2000即可,但是,这种方法对于紧急情况可能还不错,而效率上就不说了。

还有,就是说,如果你的长度不会超过2000,就建议用varchar2,但是需要注意的是数据库字符集应该是UTF-8的,对于UTF-8或欧洲的某些字符集,oracle在存储时,对于一个字符需要2个或3个字节的存储空间,虽然表定义中varchar2(4000),但是其实该字段的data_length为其2倍或3倍长。

 

在这里,也顺便把在网上看到的,关于hibernate修改配置的方法,粘贴出来.

 

Hibernate實體對象中的数据成员类型为String,映射的数据库字段类型为org.springframework.orm.hibernate.support.ClobStringType 。實例如下:

 

 

@SuppressWarnings( " serial " )
 @Entity
 @Table(name = " GUIDE " )
 // @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
 public class Guide {
     
      @Type(type = " org.springframework.orm.hibernate3.support.ClobStringType " )
      private String content; // 内容
 
           // get & set 
 } 

 

如果使用Spring的这个Clob类型就需要在applicationContext.xml中的sessionFactory bean里注入oracleLobHandler bean。下面給出Oracle數據庫的LobHandler配置

 

 

< bean id ="oracleLobHandler" 
        class ="org.springframework.jdbc.support.lob.OracleLobHandler" 
        lazy-init ="true" >   
      < property name ="nativeJdbcExtractor" ref ="nativeJdbcExtractor" /> 
 </ bean >     
 
 < bean id ="nativeJdbcExtractor"         class ="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor" 
        lazy-init ="true" />   
 
 <!-- Hibernate SessionFactory --> 
 < bean id ="sessionFactory" class ="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" > 
      < property name ="dataSource" ref ="dataSource" /> 
      < property name ="configLocation" value ="classpath:hibernate/hibernate.cfg.xml" /> 
      < property name ="hibernateProperties" > 
          < value > 
            
          </ value > 
      </ property > 
      < property name ="lobHandler" ref ="oracleLobHandler" /> 
 </ bean > 
 

LobHandler 需要访问本地 JDBC 对象,这一任务委托给 NativeJdbcExtractor Bean 来完成,NativeJdbcExtractor是一個本地JDBC對象抽取器,因此我們为 LobHandler 注入了一个 nativeJdbcExtractor。最后,我们把 lobHandler Bean 注入到需要进行 LOB 数据访问操作的sessionFactory Bean中或者直接注入到dao Bean中去。

大家可能已经注意到 nativeJdbcExtractor 和 oracleLobHandler Bean 都设置为 lazy-init="true",这是因为 nativeJdbcExtractor 需要通过运行期的反射机制获取底层的JDBC 对象,所以需要避免在 Spring 容器启动时就实例化这两个Bean。
如果底層數據庫是 DB2、SQL Server、MySQL 等非 Oracle 的其它數據庫,则只要简单配置一个 DefaultLobHandler 就可以了,如下所示:

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

 < bean id ="testDao" class ="com.test.dao.jdbc.TestJdbcDao" > 
     < property name ="lobHandler" ref =" defaultLobHandler" /> 
 < property name ="jdbcTemplate" ref ="jdbcTemplate" /> 
 </ bean > 
 

 

DefaultLobHandler 只是简单地代理标准 JDBC 的 PreparedStatement 和 ResultSet 对象,由于并不需要访问数据库驱动本地的 JDBC 对象,所以它不需要 NativeJdbcExtractor 的帮助。

 

希望总有一张方法能帮你解决掉麻烦的ORA-01461

 

 

如果,哪位有更好的解决方法,就麻烦分享一下了。

 

 

 

 

你可能感兴趣的:(spring,oracle,Hibernate,bean,jdbc)