`

“ORA-01461: 仅可以为插入 LONG 列的 LONG 值赋值”解决办法

阅读更多

以前寫過的一篇博文中提到了出現“ORA-01461: 仅可以为插入 LONG 列的 LONG 值赋值”的原因,并給出了原因和解決方法,在這裡回顧一下。(詳見 当遇到“数据大小超出此类型的最大值”和“仅可以为插入 LONG 列的 LONG 值赋值”时...   )

當時的環境: 
数据库:Oracle 9i
数据库字段类型:varchar2(4000)
输入汉字:大于1000字

原因:
   我的数据库字符集应该是UTF-8的,对于UTF-8或欧洲的某些字符集,oracle在存储时,对于一个字符需要2个或3个字节的存储空间,虽然表定义 中为varchar2(4000),但是其实该字段的data_length为其2倍或3倍长。这种情况下oracle会把data_length长度超 过4000的当做LONG型处理,你的表中有两个这样的字段,插入数据时相当于同时操作2个LONG字段,所以报错。

當時的解决办法:建议减小字段长度或拆分。实在需要的,可以转而采用CLOB字段类型。


現在的環境:

開發框架:Spring 2.0.6 + Hibernate 3.2
數據庫:Oracle 9i
数据库字段类型:CLOB
输入字節:1000 ~ 2000

現在的問題:
現 在的項目中我采用了CLOB字段類型,但又遇到了這個錯誤。当我对Oracle数据库中的CLOB字段进入insert或update操作的时候,后台出 现 java.sql.SQLException:   ORA-01461: 仅可以为插入 LONG 列的 LONG 值赋值。这个错误的特點是,当插入的数据长度小於1000字節或者大於2000字節時都不會報錯,一旦插入的数据长度在1000 ~ 2000之間時就會報錯。經過google一番之後,ORA-01461錯誤是一個經典問題了,有人認為是CLOB字段本身的問題。

解決方法:

方法1:
采用Oracle 10g最新的ojdbc14.jar驱动替換原有的驅動即可。試過了這種方法,但是并沒有生效。

方法2:

1. 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 
}


2. 如果使用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: 仅可以为插入 LONG 列的 LONG 值赋值”時,希望這個方法能夠幫您順利拿下ORA-01461。



PS:給出Oracle下幾種大容量字段類型的解釋

LONG: 可变长的字符串数据,最长2G,LONG具有VARCHAR2列的特性,可以存储长文本一个表中最多一个LONG列
LONG RAW : 可变长二进制数据,最长2G
CLOB :  字符大对象Clob 用来存储单字节的字符数据
NCLOB : 用来存储多字节的字符数据
BLOB : 用于存储二进制数据
BFILE : 存储在文件中的二进制数据,这个文件中的数据只能被只读访。但该文件不包含在数据库内。bfile字段实际的文件存储在文件系统中,字段中存储的是文件定位指针.bfile对oracle来说是只读的,也不参与事务性控制和数据恢复。
  
其 中CLOB,NCLOB,BLOB都是内部的LOB(Large Object)类型,最长4G,没有LONG只能有一列的限制。要保存图片、文本文件、Word文件各自最好采用那種数据类型呢?BLOB最好,LONG RAW也不错,但Long是oracle将要废弃的类型,因此建议用BLOB。

分享到:
评论
4 楼 foreach4 2014-12-02  
public class Test{
    public static void main(String[] args){
        out.println("Hello World!");
    }
}
3 楼 zhengyuyan1990 2012-11-08  
姐也出现了这错误,问题是,中文就报错
是从jsp里传入数据的
如果直接直接从数据库中里插入,绝对没有问题
2 楼 longrm 2011-01-20  
没看明白,能解释一下么
1 楼 gongmingwind 2010-02-05  
我也遇到了和您一样的问题,不明白为什么:当插入的数据长度小於1000字節或者大於2000字節時都不會報錯,一旦插入的数据长度在1000 ~ 2000之間時就會報錯,原因到底是什么呢??

相关推荐

    ORA-01461 仅可以为插入 LONG 列的 LONG 值赋值”解决办法

    “ORA-01461: 仅可以为插入 LONG 列的 LONG 值赋值”

    ojdbc14_10.2.0.5.jar

    Oracle Database 10g Release 2 (10.2.0.5) JDBC Drivers 2011.10.19最新驱动 能够解决诸如:ORA-01461: 仅可以为插入 LONG 列的 LONG 值赋值”这样的错误。

    Oracle_11g_JDBC_ojdbc6.rar

    ORA-01461 仅可以为插入 LONG 列的 LONG 值赋值”解决办法,jar包冲突,解决办法。

    Oracle中Clob类型处理解析收藏

    最近利用NHibernate映射类型为Clob字段在插入数据时发现当字符的字节数(一个半角字符一个字节,一个全角字符两个字节)在2000-4000之间时报错(ORA-01461:仅可以插入LONG列的LONG值赋值)。经过不断查找资料和自己...

    orcale常用命令

    例:为test表增加一列Age,用来存放年龄 sql&gt;alter table test add (Age number(3)); 修改基表列定义命令如下: ALTER TABLE 表名 MODIFY (列名 数据类型) 例:将test表中的Count列宽度加长为10个字符 sql&gt;...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

     删除HKEY_CLASSES_ROOT目录下所有以Ora、Oracle、Orcl或EnumOra为前缀的键。  删除HKEY_CURRENT_USER/SOFTWARE/Microsoft/windows/CurrentVersion/Explorer/MenuOrder/Start Menu/Programs中所有以oracle 开头...

    PHP基础教程 是一个比较有价值的PHP新手教程!

    你可以用以下的语句来为一个数值赋值: $a = 1234; # 十进制数 $a = -123; # 负数 $a = 0123; # 八进制数 (等于十进制数的83) $a = 0x12; # 十六进制数(等于十进制数的18) $a = 1.234; # 浮点数"双精度数" $a = 1.2...

    最全的oracle常用命令大全.txt

    例:为test表增加一列Age,用来存放年龄 sql&gt;alter table test add (Age number(3)); 修改基表列定义命令如下: ALTER TABLE 表名 MODIFY (列名 数据类型) 例:将test表中的Count列宽度加长为10个字符 sql&gt;...

Global site tag (gtag.js) - Google Analytics