用的是oracle9
有一个字段设置为vchar(4000)
hibernate 映射为: <property name="complainPosition" column="complain_position" type="string" length="4000" />
obj.set....
使用template.update(obj)
当数据str.getBytes().length >2000的时候就报错:数据大小超出此类型的最大值客户要求允许 2000个汉字,求指导。我不想用clob类型!另外附上一个问题:由于这样要求的字段有两个,都必须要2000个汉字,一个字段是问题,一个字段是解决办法。
配置文件为<property name="dealSituation" column="deal_situation" type="text" />
当我用两个同时用clob的时候,当其中一个数据str.getBytes().length =2500的时候,可以正常保存。
当两个字段同时插入str.getBytes().length =2500的汉字的时候,就报错:
ORA-01483: DATE 或 NUMBER 绑定变量的长度无效我已经疯掉了,以前用sql2000,直接在数据库里设置为text或者长度为4000的字段,都不会出现问题,
神马2000个汉字都能像我们所知道的那样正常保存。PreparedStatement对字符串的要求是不能超过2000,
可以通过stmt.setCharacterStream(1, new InputStreamReader(String内容, String内容.length()); 
来调整。
不过我现在是用的hibernate来保存的,虽然show_sql打印发现hibernate也是用的预处理,但我没办法调整它的长度限制
求大侠来指点迷津。。经过询,我大致知道的原因是,

解决方案 »

  1.   

    varchar2(4000) 改为NVARCHAR2(4000)
    可以插4000个汉字
      

  2.   


    ++如果你觉得不行。。建议你改用text类型
      

  3.   

    大家好,可能大家没搞清楚,
    现在不是我数据库容不下这些字。
    我现在插的一段话汉字才700多,加上一次字符等,只有2500个长度。
    数据长度是够的,
    但问题是hibernate保存的时候出错。
      

  4.   

    另外,我试过,NVARCHAR2最大只有2000,不能设置成4000
      

  5.   

    用blob吧,你超过了最大数,肯定不行
      

  6.   

    大哥位,我的问题,现在不是字段长度不够哇,
    是hibernate对oracle支持貌似有问题,插入超过1000个汉字都成问题
    建议我用clob的,看看我下面的,
    我已经做过测试了,但遇到了新问题
      

  7.   

    先copy一段我做测试的文字:
    查看用户漫游VLR地址为00821600900017,可以正常主叫、收发短信说明用户的位置更新、国际漫游、国际长途等用户数据正常。在软交换做跟踪,发现用户做被叫时可正常取用户漫游号码,但在软交换汇接局收到IAM消息6秒后,主叫端局REL拆线,原因为“recovery on timer expiry(106)”。 经过多次测试,同时发现IAM后,有时韩国VLR会回送ACM,有时并未回送ACM,但始终表现为主叫端局REL(主叫为PSTN和手机均无法正常呼通漫游用户)。在主叫MSC指令CTRAI进行跟踪,发现起呼后要等待很长时间(约20秒以上)才能正常返回MSRN。回送MSRN后,可正常占用到软交换汇接路由设备。说明此时主叫端局已发送了IAM消息。 跟踪主叫号码返回的EOS代码为2552,含义为“手机发起的断开连接,非正常挂机”。因MSRN回送较慢,在HLR上确认用户是否有签约消息。最终确认漫游用户为VPMN用户,SK=3。所以尝试取消漫游用户的签约消息,取消OCSI、TCSI后,用户可立即正常被叫,接通率100%。同时接续速度明显提高。判断问题与VPMN流程相关。恢复用户的签约消息后,在SCP侧进行CAMEL消息跟踪,对比正常的VPMN流程,发现IDP消息有差异。7、 通过以上对比,发现异常流程中的IDP被叫用户位置信息和状态信息均未正a常提供。根据MAP PAHSE 2+的流程图,可以判断漫游地VLR未正常回送PSI_ACK消息。因为漫游地的VLR支持MAP2+版本,但又无法正常回送PSI_ACK,因此主叫端局等待20秒后超时(端局参数设置),只返回HLR中的VLR地址,被叫状态、LAI等信息均未提供。同时根据3GPP规范“5.2.1.3 Receipt of a CALL PROCEEDING message”规定:手机上发setup后启动T303;收到call proceeding后,复位T303并启动T310;收到progress或者alerting后复位T310。因此当主叫手机发起setup,并收到call proceeding,但在30秒内未收到progress或者alerting,导致T310(T310通常设置为30秒)超时。手机会自动释放呼叫。T310时长30秒,PSI消息超时用去20秒,因此用户被叫用户接续的正常时间只有10秒,用于国际长途的接续时间非常有限,因此造成了被叫接续困难的情况。最后在爱立信端局上修改PSI_ACK消息的超时门限,避免因PSI_ACK超时而花费过多接续时长。
      

  8.   

    上面那段文件,我可以用plsql直接插入进库,
    但通过页面提交到后台,hibernate保存出错。
    所以,应该不是数据库长度不足,而是hibernate有错误。原因,我在上面分析过了:
    PreparedStatement对字符串的要求是不能超过2000,
    可以通过stmt.setCharacterStream(1, new InputStreamReader(String内容, String内容.length());  
    来调整。现在用show_sql打印发现hibernate也是用的预处理,但我没办法调整它的长度限制
    求大侠来指点迷津。。
      

  9.   

    hibernate版本:  
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" singleton="true" lazy-init="default" autowire="default" dependency-check="default">
        <property name="dataSource">
          <ref bean="dataSource" />
        </property>
      

  10.   

    hibernate解决不了的话,可以考虑JDBC解决。
      

  11.   

    另外补充,我的数据为字符集为:ZHS16GBK
    理论上是一个汉字点两个字节。
    我做了一个vchar2(6)做测试,
    可以保存3个汉字。
      

  12.   

    其实,我虽然找出这了这么多问题,
    但我还是不想用jdbc来解决。
    以后还有好多事情要用hibernate。
    特别是遇到要存2000个汉字的问题,难道以后都不能用hibernate做保存2000汉字的问题?
    所以我非常想把这个问题解决掉。
      

  13.   

    大侠们,你们难道就没有跟我相似的状况?
    hibernate3
    oracle9
    两个vchar2(4000)
    然后把我那段话保存试下?你们如果是正常的,请告诉 我实现方式,
    如果不正常,请帮忙来一起想办法解决
      

  14.   

    解决PreparedStatement的setString中字符串长度问题可以有两种办法:
    1、使用setCharacterStream()方法;
    2、使用OCI驱动连接Oracle数据库。另外可以试下用最新的oracle jdbc驱动
      

  15.   

    Looking for Sr Software telents,and "客户总监"and so on,base in Beijing,wellcome to contact me:[email protected] .Thanks!
      

  16.   

    使用setCharacterStream()方法中文字符也最多只能1400个左右。
    建议用CLOB,也可以试下用最新的ORACLE JDBC驱动包,有网友说可以解决问题。
      

  17.   

     我基本没法用setCharacterStream了,
    至于包,我用的是ojdbc14.jar了
      

  18.   

    是不是你在页面中或者服务器中使用了例如UTF-8的字符集,在UTF-8字符集中一个汉字是占3位长度的
      

  19.   

    没有吧,现在代码都utf-8编码的,但跟存数据库有什么关系
      

  20.   

    页面上如果是utf-8的字符集,存入数据库时一个汉字是占三位长度的
      

  21.   

    这个是Oracle驱动的问题,与Hibernate没有什么关系,你直接使用JDBC中的setString方法应该也是一样无法支持超过2000个中文的
    你考虑使用CLOB吧,不过说话Oracle中操作CLOB是最最最最恶心!没有之一
      

  22.   

    难道这就是最终结果吗?用hibernate,不用clob,就最多只能插666个汉字吗?
    没有解决办法吗?
      

  23.   

    跟你数据库的字符集有关,不是页面的字符集。数据库用AL32UTF8的话,一个汉字三个字符
      

  24.   

    31楼,你确定你学习到了?我这儿的NVARCHAR2(4000)不成功,只设置2000长度
    如果你混分就算了。
    再请问各位大侠:
    用hibernate,不用clob,就最多只能插666个汉字吗?
    没有解决办法吗?
      

  25.   

    NVARCHAR2应该与国家字符集有关,自己去百度google都行,这种问题不需要这里问啦。
      

  26.   

    楼上的,确实跟数据库没关系,
    现在nvarchar2(4000)
    我现在数据库的安装字符集是gbk,所以肯定可以存2000个汉字,
    但我现在用hibernate保存报错了,这个错误hibernate的问题,具体我前面都说了。
    建议你看看我前面描述的问题原因,
    看你说的这么简单,希望你自已在你本机做个小例子测试,有没有问题?如果没有,请告诉我怎么做的。如果有问题,我们一起找解决。
    我这个问题不在这儿问应该去哪儿问,我都百度google了几天了
      

  27.   


    nvarchar(4000)不能把 最多就2000汉字
      

  28.   

    难道没办法了吗?不用clob 就不行?
      

  29.   

    如你所说,我没看明白;
    如果不是字符串本身存在乱码导致长度不对的话,你试试在hibernate配置数据源的时候指定一下字符集,characterEncoding,呵呵,瞎猜的,没根据哦
      

  30.   

    你数据库是Oracle9i的吧?
    换成10G的驱动,或者换数据库字段的类型,或者换数据库为10g,
    Oracle9i的BUG,你懂得。
      

  31.   

    现网系统部署的就是9i,而且用的是jdk4.。
    这些我都不可能改变的,真的是它的bug吗?没有别的办法了?
      

  32.   

    实在不行就用2个字段分开存,select 时再合并2个字段的值。
      

  33.   

    能把hibernate报错信息发出来么?
      

  34.   

    字节数有上限4000,再大了就要用clob了。nvarchar2可以设置字符数,不是字节数,但是要满足字节数上限不能超过4000的要求。
    应该是这样,
      

  35.   


    以下引用网上的说明:Oracle 9i 的 varchar2 最大可存 32,767 bytes.
    直接存进 varchar2 只能存 4,000 bytes,
    间接存就可存到 32,767 bytes.你的 666 汉字所用的编码里 (可能是 UTF8) 每个字占了 3 bytes,
    当你存的时候, 没有作好 charset-encoding 的转换,
    造成你的每个 byte 被当成是 java 的一个 char (2 bytes) 来存,
    总言之, 你的每个汉字要用 3x2=6 bytes 存进 oracle 中,
    所以最多只能存到 4000/6=666 字.如果你的汉字每个字只用 2 bytes,
    而且存的过程正确,
    那摸最多就可以存到 16,000 多个字了.
    其实是JDBC驱动的BUG,听说换最新版版的Oracle驱动可以解决,不过我们那项目最后是直接换的数据库,你可以试试~
      

  36.   

    楼主,你这个问题应该是字符编码的问题,使用不同的编码获取的byte是不一样的,你可以测试一下!
      

  37.   

    楼上说得比较接近了,
    我在页面写3个汉字,
    在后台取的时候,用str.getByte().length的结果是 9
    也就是一个汉字占3个字节。
    然后,hibernate中对象的赋值obj.set...
    对于字符串型 ,最大只能只能长度为2000
    (注意,这个地方不能用str.length()来计算长度,而要用str.getByte().length来计算长度。)
    这样的结果就是:hibernate最多能接收的汉字是666左右。这是hibernate的问题的,可能是由于连接了oracle的驱动,才会这样。因为我在sql2000数据库中没有这种问题。
    另外,我这是没办法换驱动和库。
    现在网运行的环境是9i和jdk4
    求指导
    附:我暂时按下面的方法应付了。
    hibernate在增加和修改的时候,对这两个大字段set成空字符串,
    后面用jdbcTemplate做更新操作
      

  38.   

    jdbc用
    stmt.setCharacterStream(1, new InputStreamReader(String内容, String内容.length());  
    接收大文本应该是正解.改用Hibernate后加载大文本,那要看具体是什么数据库,在它的方言中是如何将Hibernate的类型与数据库字段类型相匹配的.
    我用过Access数据库(小玩具),我看了一下Hibernate操作它的方言,它就是用:
     // Access: MEMO is 65,535 characters; 2.14 GB if not binary data
     registerColumnType( Types.BLOB, "memo" ); // so that's 65,535 characters in Access
     registerColumnType( Types.CLOB, "memo" ); // so that's 2.14 GB in Access
    这就是它的映射. 而我的实体类用的也是String.
    ---------------------------------
    Hibernate插进来之后,应该有三家数据类型:
    一家是实体类的实例字段用什么数据类型,
    一家是数据库的字段用什么数据类型,
    还有一家是Hibernate用的是什么数据类型.
    此时,我们好像看不见sql的数据类型.
    而数据库的字段类型与Hibernate的类型如何匹配,是放在方言文件中定义的!换句话说,你要想让数据库接收大文本,是不是应该找到数据库的什么类型的字段与Hibernate的CLOB匹配.找到后,通过调整数据库字段的数据类型来达到设计目的.
    ------------------------------
    以上供参考.
      

  39.   

    我是刚出来练手的,你在映射文件内映射类型改用text可不可以,然后hibernate配置文件里<session-factory>下加
    <property name="hibernate.connection.SetBigStringTryClob">true</property>
      

  40.   

    在前插入代码处理下字符串:
      
    String  str=要插入的值;
    if (str != null) {   
       byte[] bs = str.getBytes("UTF-8");
       //用新的字符编码生成字符串
       str= new String(bs, "GBK");
      }else{
     str="";
    }
    System.out.print(str);
      

  41.   

    57楼给出了专业的分析,不知道有没有可能在代码里面对hibernate自已的类型做个定义,让它能接受大一点的数据?
    60楼,我去试试。
    61楼,我觉得可行,而且看上去可以解决我的问题,如果改成GBK的,那么一个汉字就只点两个字节了,我得试试才知道当然也期待更多的回复,能给出一个最终解决办法
      

  42.   

    ORACLE的BUG长度在1000-2000会出现这个问题,你试试看加空格,加到超过2K就可以保存了取值啥的操作时候再过滤掉空格。
      

  43.   

    UTF字符集有占用 3、4个字节的汉字。
      

  44.   

    我有一个文档习作,数据使用PostgreSQL数据库,持久化使用了Hibernate,服务器用的resin.
    以前做的,今天下午专门调出来试了一下. 大文本字段一条可存260k(没再加码试了).部分配置如下:表结构:
    CREATE TABLE OA_DOCUMENT(
      GID           AUTOINCREMENT(1,1) PRIMARY KEY,
      GHEADING      VARCHAR(255),
      GKEYWORD      VARCHAR(255),
      GCOUNTER      INT,
      GBUILDTIME    TIMESTAMP,
      GUPDATETIME   TIMESTAMP,
      GMATTER       NOTE,                  //这个是大文本字段
      GUSERID       INT,
      GLOCKUP       BIT,
      GCONTENT_TYPE VARCHAR(255),
      GSHOWSCOPE    VARCHAR(255)
    );
    ==========================================
    hibernate.cfg.xml
    <?xml version='1.0' encoding='UTF-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
              "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
              "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
    <!-- Generated by MyEclipse Hibernate Tools. -->
    <hibernate-configuration>
    <session-factory>
      <property name="connection.datasource">java:comp/env/jdbc/DefaultDS</property>
      <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property>
      <property name="show_sql">true</property>
      <property name="hibernate.cache.user_query_cache">true</property>
      <property name="hibernate.cache.use_structured_entries">true</property>
      <property name="hibernate.current_session_context_class">thread</property>
      <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
      <property name="net.sf.ehcache.configurationResourceName">ehcache.xml</property>
      <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
      <property name="hibernate.transaction.auto_close_session">false</property>
      <mapping class="gsy.document.entity.Document"/>
    </session-factory>
    </hibernate-configuration>中间层DAO用泛型做的,很平常.
    Document 实体类中大文本字段用的是String型.
      

  45.   

    很显然你用的是 UTF-8UTF-8 的话 varchar2(4000) 只能存放 1333 个汉字,nvarchar2 最大值也只能到 1333 个汉字。
      

  46.   

    执行:select   vsize( '汉')   from   dual; 结果为2,
    select * from nls_database_parameters;  结果中:
    NLS_CHARACTERSET=ZHS16GBK
    NLS_LENGTH_SEMANTICS=BYTE
      

  47.   

    hibernate报的错误叫:数据大小超出此类型的最大值
      

  48.   

    java.sql.SQLException: 数据大小超出此类型的最大值: 3498
    at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)
    at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179)
    at oracle.jdbc.ttc7.TTCItem.setArrayData(TTCItem.java:147)
    at oracle.jdbc.dbaccess.DBDataSetImpl.setBytesBindItem(DBDataSetImpl.java:2492)
    at oracle.jdbc.driver.OraclePreparedStatement.setItem(OraclePreparedStatement.java:1194)
    at oracle.jdbc.driver.OraclePreparedStatement.setString(OraclePreparedStatement.java:1614)
    at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.setString(DelegatingPreparedStatement.java:132)
    at org.hibernate.type.StringType.set(StringType.java:26)
    at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:136)
    at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:107)
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2002)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2376)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2312)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2612)
    at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:96)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
    at org.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:394)
    at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:367)
    at org.springframework.orm.hibernate3.HibernateTemplate.update(HibernateTemplate.java:636)
    at org.springframework.orm.hibernate3.HibernateTemplate.update(HibernateTemplate.java:632)
    at com.wri.hy.framework.application.framework.dao.hibernate.CommonDaoImpl.updateObj(CommonDaoImpl.java:237)
    at com.wri.hy.jcssv3.app.web.knowledge.CaseController.save(CaseController.java:269)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.web.servlet.mvc.multiaction.MultiActionController.invokeNamedMethod(MultiActionController.java:433)
    at org.springframework.web.servlet.mvc.multiaction.MultiActionController.handleRequestInternal(MultiActionController.java:371)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:45)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:797)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:727)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:396)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:360)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.wri.hy.framework.util.EncodingFilter.doFilter(EncodingFilter.java:70)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:619)
      

  49.   

    提醒:UTF8编码一个汉字3个字节
      

  50.   

    我以前做过一个项目遇到过这个问题感觉很诡异 插入2000就报错 2000以上以下就OK具体原因现在也忘了
    解决方法就是在Hibernate实体 该字段前加上说明@Type(type  =   " org.springframework.orm.hibernate3.support.ClobStringType " )
    private String prdDescHtml; 当然这个是基于Spring提供的Hibernate模板来操作的
      

  51.   

    //我插入的时候是调用的存储过程
     OracleDatabase db = (OracleDatabase)DataRegester.CreateDatabase();
     OracleCommand commandWrapper = (OracleCommand)db.GetStoredProcCommand("NRGLB_Insert"); db.AddParameter(commandWrapper, "PNR", OracleType.Clob, entity.NR.Length, ParameterDirection.Input, true, 0, 0, "NR", DataRowVersion.Current, entity.NR);
      

  52.   

        
        你查看一下你的oracle9i的小版本号,是不是oracle 9i.2.3,然后换乘oracle 9i.2.4的驱动试试,也就是3版本以上的驱动包,注意是小版本号。
      

  53.   

    ORACLE9i的版本号有
    91和92普遍用的是92版本而92版本又分为:
    9201
    9204
    9206
    9208你换乘9204的驱动包,应该就好了。
      

  54.   

    投机取巧
    在实体类中
    在映射文件中不要写 length="4000" />public class Test{private String complainPosition;public void setComplainPosition(String s){
    if(s.length()>2000)
    return;
    else
    this.complainPosition = s;
    }