我的配置是spring1.2+hibernate3+strut1.2,数据库Oracle9
数据源在tomcat中,配置为:
<Context path="/***" docBase="***" debug="0" reloadable="true">
 <Resource name="jdbc/***" auth="Container" 
   type="javax.sql.DataSource"
   username="***" password="***"
            driverClassName="oracle.jdbc.driver.OracleDriver"
   url="jdbc:oracle:thin:@*.*.*.*:1521:***" 
            maxActive="4" maxIdle="2"/>
  <ResourceLink name="UserTransaction"
            global="UserTransaction"
            type="javax.transaction.UserTransaction"/>
</Context>
表的字段类型是varchar(4000);这里不能用clob,Blob(必要条件)
我想存入1000个汉字,实际输入900个就报这个错误:
- SQL Error: 17070, SQLState: null
- 数据大小超出此类型的最大值: 2700
- Could not synchronize database state with session
- [e] (HibernateTemplate): encountered SQLException [数据大小超出此类型的最大值: 2700]; nested exception is java.sql.SQLException: 数据大小超出此类型的最大值: 2700
org.springframework.jdbc.UncategorizedSQLException: (HibernateTemplate): encountered SQLException [数据大小超出此类型的最大值: 2700]; nested exception is java.sql.SQLException: 数据大小超出此类型的最大值: 2700
java.sql.SQLException: 数据大小超出此类型的最大值: 2700
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:2461)
at oracle.jdbc.driver.OraclePreparedStatement.setItem(OraclePreparedStatement.java:1155)
at oracle.jdbc.driver.OraclePreparedStatement.setString(OraclePreparedStatement.java:1572)
at org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement.setString(DelegatingPreparedStatement.java:131)
at net.sf.hibernate.type.StringType.set(StringType.java:26)
at net.sf.hibernate.type.NullableType.nullSafeSet(NullableType.java:48)
at net.sf.hibernate.type.NullableType.nullSafeSet(NullableType.java:35)
at net.sf.hibernate.persister.EntityPersister.dehydrate(EntityPersister.java:387)
at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:460)
at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:436)
at net.sf.hibernate.impl.ScheduledInsertion.execute(ScheduledInsertion.java:37)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2449)
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2435)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2392)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2261)
at net.sf.hibernate.transaction.JTATransaction.commit(JTATransaction.java:52)
at org.springframework.orm.hibernate.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:472)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:397)
at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(TransactionAspectSupport.java:243)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:66)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:144)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:174)
我试了用了Oracle10的ojdbc14.jar放在tomcat\common\lib下,可是不行。那位达人能提供些解决的方案,在下不胜感激!

解决方案 »

  1.   

    根据网上一位网友的介绍,这是一个Oracle JDBC Driver的Bug。
    原因是PreparedStatement的setString()会预检查数据类型,而这部分代码未考虑双字节字符的问题,所以就误报了。
    解决方案:不用PreparedStatement,而直接组成sql语句插入。弊端是需要自己实现一个字符串转义过程,效率也稍微差那么一点点吧。建议用CLOB字段来解决比较好。
      

  2.   

    你把varchar(4000)改为varchar2(4000)试一试
      

  3.   

    改成varchar2或nvarchar都不可以的。会出现一样的问题。
      

  4.   

    我现在已经实现了插入1000个字段,方法是在Hibernate的回调函数中使用JDBC,但有个问题,如果插入的内容有单引号就会报错,我是在存入数据库之前把'变成’,下面是代码,如果那位有同样的问题,希望能有所帮助。
    public void saveAnswerRecord(final AnswerRecord answerRecord){
    getHibernateTemplate().execute(new HibernateCallback(){
    public Object doInHibernate(Session session) throws HibernateException, SQLException {
    String sql = "insert into TBL_ANSWER_RECORD (" +
    "RECORD_ID,MAIN_SHEET_FLOW_NO,BEGIN_TIME,END_TIME," +
    "ANSWER_AGENT_CODE,ANSWER_CONTENT,RECORD_TYPE,RECORD_RESULT) " + 
             "values(" + 
             "\'" + answerRecord.getRecordID() + "\'," + 
             "\'" + answerRecord.getMainSheetFlowNO()+ "\'," +
             "\'" + answerRecord.getBeginTime() + "\'," +
             "\'" + answerRecord.getEndTime() + "\'," +
             "\'" + answerRecord.getAnswerAgentCode() + "\'," +
             "\'" + answerRecord.getAnswerContent() + "\'," +
             "\'" + answerRecord.getRecordType() + "\'," +
             "\'" + answerRecord.getResult() + "\'" +
             ")";
    Connection conn = session.connection();
    Statement stmt = conn.createStatement();
    boolean result = stmt.execute(sql);
    if(!result){
    System.out.println("*********插入 TBL_ANSWER_RECORD 成功************");
    }
    return null;
    }
    });
    }
      

  5.   

    你用PreparedStatement应该就不会有单引号报错的问题。