当前位置:   article > 正文

HibernateException: IOException occurred reading text + java.io.IOException: 违反协议: [14,0]

ioexception occurred reading text

环境:

Hibernate 4.2.7.SP1

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0  64bit production

OJDBC7:12.1.0.1


报错:

数据:向数据库中插入一条数据,数据中某一个字段是CLOB类型,长度为4193个字符

报错异常:

  1. 2020-05-20 11:47:23,950 [qtp1288052401-61] c.p.p.m.d.ModelDao ERROR IOException occurred reading text
  2. org.hibernate.HibernateException: IOException occurred reading text
  3. at org.hibernate.type.descriptor.java.DataHelper.extractString(DataHelper.java:94) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  4. at org.hibernate.type.descriptor.java.DataHelper.extractString(DataHelper.java:280) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  5. at org.hibernate.type.descriptor.java.StringTypeDescriptor.wrap(StringTypeDescriptor.java:89) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  6. at org.hibernate.type.descriptor.java.StringTypeDescriptor.wrap(StringTypeDescriptor.java:39) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  7. at org.hibernate.type.descriptor.sql.ClobTypeDescriptor$1.doExtract(ClobTypeDescriptor.java:60) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  8. at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  9. at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:261) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  10. at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:257) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  11. at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:247) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  12. at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:332) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  13. at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2926) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  14. at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1673) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  15. at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1605) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  16. at org.hibernate.loader.Loader.getRow(Loader.java:1505) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  17. at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:713

 

  1. Caused by: java.io.IOException: 违反协议: [ 14, 0, ]
  2. at oracle.jdbc.driver.OracleClobReader.needChars(OracleClobReader.java:264) ~[ojdbc7-12.1.0.1.jar:12.1.0.1.0]
  3. at oracle.jdbc.driver.OracleClobReader.read(OracleClobReader.java:195) ~[ojdbc7-12.1.0.1.jar:12.1.0.1.0]
  4. at org.hibernate.type.descriptor.java.DataHelper.extractString(DataHelper.java:86) ~[hibernate-core-4.2.7.SP1.jar:4.2.7.SP1]
  5. ... 119 more
  6. Caused by: java.sql.SQLException: 违反协议: [ 14, 0, ]
  7. at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:669) ~[ojdbc7-12.1.0.1.jar:12.1.0.1.0]
  8. at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:249) ~[ojdbc7-12.1.0.1.jar:12.1.0.1.0]
  9. at oracle.jdbc.driver.T4C8TTIClob.read(T4C8TTIClob.java:245) ~[ojdbc7-12.1.0.1.jar:12.1.0.1.0]
  10. at oracle.jdbc.driver.T4CConnection.getChars(T4CConnection.java:3901) ~[ojdbc7-12.1.0.1.jar:12.1.0.1.0]
  11. at oracle.sql.CLOB.getChars(CLOB.java:517) ~[ojdbc7-12.1.0.1.jar:12.1.0.1.0]
  12. at oracle.jdbc.driver.OracleClobReader.needChars(OracleClobReader.java:245) ~[ojdbc7-12.1.0.1.jar:12.1.0.1.0]

源码分析:

  1. public static String extractString(Reader reader, int lengthHint) {
  2. // read the Reader contents into a buffer and return the complete string
  3. final int bufferSize = getSuggestedBufferSize( lengthHint );
  4. final StringBuilder stringBuilder = new StringBuilder( bufferSize );
  5. try {
  6. char[] buffer = new char[bufferSize];
  7. while (true) {
  8. int amountRead = reader.read( buffer, 0, bufferSize );
  9. if ( amountRead == -1 ) {
  10. break;
  11. }
  12. stringBuilder.append( buffer, 0, amountRead );
  13. }
  14. }
  15. catch ( IOException ioe ) {
  16. throw new HibernateException( "IOException occurred reading text", ioe );
  17. }
  18. finally {
  19. try {
  20. reader.close();
  21. }
  22. catch (IOException e) {
  23. LOG.unableToCloseStream( e );
  24. }
  25. }
  26. return stringBuilder.toString();
  27. }

调试追踪到Hibernate在读取CLOB字段转换为String数据类型时,在read方法处抛出异常:int amountRead = reader.read( buffer, 0, bufferSize );

继续往里追踪,发现,read方法调用的是ojdbc7驱动中的OracleClobReader.read(char[] var1, int var2, int var3)方法:

  1. public int read(char[] var1, int var2, int var3) throws IOException {
  2. this.ensureOpen();
  3. int var5 = var2 + Math.min(var3, var1.length - var2);
  4. if (!this.needChars(var5 - var2)) {
  5. return -1;
  6. } else {
  7. int var4;
  8. for(var4 = var2 + this.writeChars(var1, var2, var5 - var2); var4 < var5 && this.needChars(var5 - var4); var4 += this.writeChars(var1, var4, var5 - var4)) {
  9. }
  10. return var4 - var2;
  11. }
  12. }

继续追踪,发现是在调用 needChars(int var1) 方法时抛出异常:

  1. protected boolean needChars(int var1) throws IOException {
  2. this.ensureOpen();
  3. if (this.pos >= this.count) {
  4. if (!this.endOfStream) {
  5. try {
  6. if (var1 > this.currentBufferSize) {
  7. this.currentBufferSize = Math.max(var1, this.initialBufferSize);
  8. PhysicalConnection var2 = (PhysicalConnection)this.clob.getInternalConnection();
  9. synchronized(var2) {
  10. this.resizableBuffer = var2.getCharBuffer(this.currentBufferSize);
  11. }
  12. }
  13. int var7 = this.currentBufferSize;
  14. if (this.maxPosition - this.lobOffset < (long)this.currentBufferSize) {
  15. var7 = (int)(this.maxPosition - this.lobOffset);
  16. }
  17. this.count = this.clob.getChars(this.lobOffset, var7, this.resizableBuffer);
  18. if (this.count < this.currentBufferSize) {
  19. this.endOfStream = true;
  20. }
  21. if (this.count > 0) {
  22. this.pos = 0;
  23. this.lobOffset += (long)this.count;
  24. if (this.lobOffset >= this.maxPosition) {
  25. this.endOfStream = true;
  26. }
  27. return true;
  28. }
  29. } catch (SQLException var6) {
  30. IOException var3 = DatabaseError.createIOException(var6);
  31. var3.fillInStackTrace();
  32. throw var3;
  33. }
  34. }
  35. return false;
  36. } else {
  37. return true;
  38. }
  39. }

经过对逻辑分析与调试,发现4193长度的字符串调用getInternalConnection会抛出异常,但是加大了了字符串长度到8193后,异常不再抛出,于是怀疑是OJDBC7这个版本的bug,升级到OJDBC7:12.1.0.2后,问题得到解决


疑问:

至于12.1.0.1版本字符串长度为4193时,调用getInternalConnection()方法后会抛出异常的原因还未深究,感兴趣的同学可以了解一下源码,看一下具体问题出现的原因。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/403464
推荐阅读
相关标签
  

闽ICP备14008679号