本人最近使用到ORACLE的CLOB字段,主要保存的是如下的字符串信息:
#
 sysname ZJ-HZ-ESN-SR-NE40E-1.MAN
#
 super password level 3 cipher ;`*aVR`/WHGQ=^Q`MAF4<1!!
#
 info-center loghost 202.96.102.228
#
 vlan batch 50 80
#
snmp-agent trap type base-trap
#
ip vpn-instance aaa
 route-distinguisher 64743:1001
#
ip vpn-instance CN2-Zhonghewangguan
 route-distinguisher 4809:4504
 vpn-target 4809:450400 export-extcommunity
 vpn-target 4809:450400 import-extcommunity
#
hwtacacs-server template zjdxnoc
 hwtacacs-server authentication 202.96.103.57
 hwtacacs-server authorization 202.96.103.57
 hwtacacs-server accounting 202.96.103.57如果字符串少的话,保存没有问题,但是 到达一定行数,比如1200 行,就会出现:
ava.sql.SQLException: Io exception: Connection reset
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146)
        at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:255)
        at oracle.jdbc.driver.T4CConnection.putChars(T4CConnection.java:2678)
        at oracle.sql.CLOB.putChars(CLOB.java:433)
        .............省略
异常,而且这个异常的地方,就是写的那个,以下是我实验过的所有写入方法  1:第一种写入方法
           sql = "select content  from tb_confing_file  "+whereSql+" for update" ;
  conn = getSession().connection();
  java.sql.Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
 
 java.sql.ResultSet rs = stmt.executeQuery(sql);
 while (rs.next()) { 
 /* 获取此clob对象 */ 
         oracle.sql.CLOB clob = (oracle.sql.CLOB)rs.getClob("content");
      
 /* 第 一种  更新数据 方法
 BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());
 BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(configUpdate.getContentStr().getBytes()));
  int charstr,count;
 count=0;
  while ( (charstr = in.read()) != -1) {
  out.write(charstr);
 System.out.println(count++); //测试发现在 count 打印 8500后,出现异常,但是如果 字符串不多,比如100行,都没有问题
  
     }
    in.close();
    out.close();
         */
         
  /* 第 二 种  更新数据  方法
      
    java.io.Writer pw = clob.getCharacterOutputStream();   
    pw.write(configUpdate.getContentStr());   //在这里出现IO 异常 
     pw.flush();   
     pw.close(); 
    
    */              
 } 


 2: 用另一种方法也是一样的有那个IO 异常,如下:
  SerializableClob  sc= (SerializableClob)tableobj.getContent();
 Clob wrapclob = sc.getWrappedClob();
 CLOB clob = (CLOB)wrapclob;
 java.io.Writer pw = clob.getCharacterOutputStream();   
 pw.write(ContentStr);   //写入出现 Io exception: Connection reset
 pw.flush();   
 pw.close();   
 

我个人感到很纳闷,表字段定义为 : CONTENT              CLOB, 网上找了好多资料,都说CLOB 字段可以保存4G的东西,可是什么我的才几K都不到到字符串,却写入不了呢?


请论坛里的牛人,大侠帮个忙,看看是什么问题。

我现在怀疑不是我的程序问题,可能是环境。

我现在的环境是 ORACEL 10G 的,JAVA是:java version "1.5.0_16" ,驱动是:ojdbc14.jar 。

以前这个程序运行都很好的,今天得到的字符串数据有点大,发现不能写入,100分请帮忙解决,或者给个思路。现在正的找不该这么解决啦。

解决方案 »

  1.   

    没看到你有使用到EMPTY_CLOB()的地方,对ORACLE的大对象类型操作,是需要进行预处理的.
      

  2.   

     
    那改怎么解决呢,我想知道,CLOB 号称可以保持4G 的数据 ,我想看看,保存那么多数据是怎么写进去的。难道不是用我上面提到的方法,还有其他写法吗?楼上的朋友,缓冲区已经满,该怎么清除呢? 
      

  3.   


    我已经预处理里,我这里省略啦,我贴出来的,是在预处理后,在通过“select colb form tabel where id=1 for update” 方式更新CLOB字段时的问题我之前预处理 的代码如下:
     configfile.setId(id);
     configfile.setContent(Hibernate.createClob(""));
     getSession().save(configfile);
     getSession().flush();
      

  4.   

    下面这个例子好象做得比较好,有注释说明,自己也收藏一下.:)
    http://www.blogjava.net/AstroQi/archive/2008/11/03/214025.html
      

  5.   

    问题依然存在,怪啦,今天怎么遇到这样的问题,难道是硬件环境问题。感觉别人都没有遇到,给我碰到啦,郁闷死啦stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT CONTENT FROM TB_CONFING_FILE WHERE "+whereSql+" FOR UPDATE");//一定要for update锁定该记录,否则抛出ORA-22920: 未锁定含有 LOB 值的行
                System.out.println("--------------------------- 22222222222222 ---------------------------------------");
                while (rs.next()) {
                    /* 取出此CLOB对象 */
                    oracle.sql.CLOB clob = (oracle.sql.CLOB)rs.getClob("CONTENT");
                    /* 向CLOB对象中写入数据 */
                    Writer out = clob.getCharacterOutputStream();
                    //out.write(new String(obj.getEmail()));//obj.getEmail()返回byte[]类型,但是当obj.getEmail()
                    //绝对大时,执行new String(byte[])时,JVM会抛出内存溢出异常
                    byte[] clobcontent = fileContent.getBytes();
                    String[] arrx = pagedClobStream(clobcontent);//要解决内存溢出异常,必须把绝对大的byte[]进行分页
                    System.out.println("--------------------------- 333333333333333333 ---------------------------------------");
                    if (arrx != null){
                        for (int i = 0; i < arrx.length; i++) {
                            out.write(arrx[i]);
                            out.flush();// 就是这里,才开始flush() 就提示 Io exception: Connection reset,下面的["+i+"] 都没有打印,说明才第一次写入都出错啦,我怀疑是不是被控制住只能写入2000个字符啊,但是哪里控制的呢?我是以CLOB方式操作的,没有以varchar方式操作啊。
                            System.out.println("--------------------------- ["+i+"] ---------------------------------------");
                        }
                    }
                    else 
                     out.write("");
                    out.close();
                }
      

  6.   

    终于解决,再次感谢sleepzzzzz 提供的 链接,回来我分页时,改为 PAGE_SIZE = 1024 *10 ;改小后,可以全部写入啦,看来一次写入还是有限制的