【问题标题】:java.sql.SQLRecoverableException: Closed Connection during receiving blob field from oracle databasejava.sql.SQLRecoverableException:从 oracle 数据库接收 blob 字段期间已关闭连接
【发布时间】:2021-02-03 10:57:51
【问题描述】:

我在从 oracle 数据库接收 blob 字段时遇到了一个奇怪的问题:“SQLRecoverableException: Closed Connection

描述此异常的堆栈跟踪:

java.sql.SQLRecoverableException: Closed Connection
    at oracle.jdbc.driver.OracleBlob.getDBAccess(OracleBlob.java:960) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.OracleBlob.getBinaryStream(OracleBlob.java:319) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.jdbc.driver.OracleBlob.getBinaryStream(OracleBlob.java:300) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at oracle.sql.BLOB.getBinaryStream(BLOB.java:316) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_221]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_221]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_221]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_221]
    at org.hibernate.engine.jdbc.SerializableBlobProxy.invoke(SerializableBlobProxy.java:60) ~[hibernate-core-5.3.18.Final.jar:5.3.18.Final]
    at com.sun.proxy.$Proxy142.getBinaryStream(Unknown Source) ~[?:?]
    at com.xxx.yyy.util.KeystoreHelper.loadKeyStore(KeystoreHelper.java:89) [cphcore-3.23.0.23-SNAPSHOT.jar:?]
    at com.xxx.yyy.bp.job.substep.ProcessIF2Files.getChannelUnsealer(IFB2UnsealFiles.java:207) [classes/:?]
    at com.xxx.yyy.bp.job.substep.ProcessIF2Files.access$4(IFB2UnsealFiles.java:198) [classes/:?]
    at com.xxx.yyy.bp.job.substep.ProcessIF2Files$1.execute(IFB2UnsealFiles.java:86) [classes/:?]
    at com.xxx.yyy.bp.job.substep.ProcessIF2Files$1.execute(IFB2UnsealFiles.java:1) [classes/:?]

源码:类KeystoreHelper方法loadKeyStore:

(...)

    Blob keystoreBlob = keystore.getKeystoreData();
    if (keystoreBlob == null || keystoreBlob.length() == 0) {
      log.error("Keystore data is empty");
      throw new KeystoreAccessException(keystore, "Keystore data is empty", null);
    }

    inputStream = keystore.getKeystoreData().getBinaryStream(); // line 89 - Exception
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    IOUtils.copy(inputStream, outputStream);
    inputStream.close();
    outputStream.close();
    byte[] keystoreData = outputStream.toByteArray();

    inputStream = new ByteArrayInputStream(keystoreData);
    
(...)

变量的源代码-keystore,类DbKeystore(实体),方法getKeystoreData:

(...)
    private java.sql.Blob keystoreData;
    
    public java.sql.Blob getKeystoreData() {
        return this.keystoreData;
    }
    
    public void setKeystoreData(java.sql.Blob keystoreData) {
        this.keystoreData = keystoreData;
    }
(...)

你们中有人遇到过类似的问题吗? 感谢您的帮助:)

【问题讨论】:

  • 很遗憾没有,顺序的变化 - .toByteArray() 没有任何变化
  • 感谢您突出显示第 89 行,keystore.getKeystoreData().getBinaryStream()。这导致了异常。不幸的是,“SQLRecoverableException”掩盖了“真正的”异常。问:getKeystoreData() 是否在自定义类中?您的组织编写的课程?问:你能用调试器进入那个类吗?
  • 1.你试过用不同的驱动(12c、18c、19c)吗 2.你试过ojdbc10.jar
  • 感谢@paulsm4 的回答,我已将getKeystoreData() 方法的定义添加到主题中,抱歉缺少此内容。 - getKeystoreData 是简单的 getter 方法。
  • @devnull 由于 jdk 8 限制,我无法使用 ojdbc10.jar 或更新版本。我检查了 ojdbc8 的最新版本 - 版本 19.7.0.0,这个版本也存在问题

标签: oracle hibernate orm blob


【解决方案1】:

我正在与@lmetrak 合作,最后我发现了问题所在。 我们的应用程序支持 Oracle 和 MSSQL 数据库。这个错误只有在我们使用 Oracle 时才会出现,因为它是由 oracle 的 BLOB 实现引起的。

@lmetrak 发布了 KeystoreHelper.class 的和平。在这里,我们没有交易。我们在上一步为数据库获取了 Keystore 实体,我们关闭了事务并将实体传递给 KeystoreHelper 类。

oracle.sql.BLOB 包含有关用于从数据库中获取实体的连接的信息。因此,当我们请求 BinaryStream 时,blob 会尝试连接到数据库以下载日期,因为它不是唯一的代理。它不会尝试从连接池中获取打开的连接,但它会尝试使用用于获取 Keystore 实体的相同连接。有时会发生连接同时关闭,然后出现错误。我不确定 MSSQL 策略是什么,但是他们的 BLOB 实现不包含有关连接的信息,并且没有这个问题。

我们的解决方案是将 Keystore.keystoreData 文件类型从 BLOB 更改为 byte[]。 现在它适用于 Oracle 和 MSSQL。

(...)

     byte[] keystoreData = keystore.getKeystoreData();
     /*A few checks*/
     inputStream = new ByteArrayInputStream(keystore.getKeystoreData());
     ByteArrayOutputStream outputStream= new ByteArrayOutputStream();
     IOUtils.copy(inputStream , outputStream);
     inputStream .close();
     outputStream.close();
     byte[] myKeystoreData = myBos.toByteArray();
     inputStream = new ByteArrayInputStream(myKeystoreData);
    
(...)

【讨论】:

    【解决方案2】:

    这很可能是由于底层 JDBC 连接被放回连接池造成的。确保您用来加载实体的 EntityManagerSession 在您访问 blob 时仍然处于活动状态。

    【讨论】:

      猜你喜欢
      • 2013-01-23
      • 1970-01-01
      • 2021-10-04
      • 2012-08-07
      • 1970-01-01
      • 2017-06-19
      • 1970-01-01
      • 2012-08-15
      相关资源
      最近更新 更多