java - 无法使用 DBCP 连接更新 CLOB

标签 java oracle jdbc clob apache-commons-dbcp

我正在尝试使用使用 Apache DBCP 连接池检索的连接对象来更新 clob 列。

早些时候,我使用 this 实现了连接池它工作正常,即能够更新 CLOB。我切换到 DBCP 是因为我遇到了 java.sql.SQLException: ORA-01000: maximum open cursors exceeded。我检查了所有 DAO 中的连接、resultSet、preparedStatement 对象。所有 finally block 都关闭了这些游标。仍然面临此错误,因此决定切换到 DBCP。

但是,当我尝试使用此 DBCP 连接更新 CLOB 时,应用程序只是在 pstmt.executeUpdate() 处挂起。

Connection conn = null;
        PreparedStatement pstmt = null;
        CLOB clob = null;
        String q = "UPDATE REPORT_TABLE SET RPT_FILE = ? WHERE RPT_SEQ_NUM = ?";
        ...
            conn = DBConnection.getConnection();
            pstmt = conn.prepareStatement(q);
            clob = getCLOB(xmlReport, conn);
            pstmt.setObject(1, clob);
            pstmt.setString(2, reportSeqNo);

            if (pstmt.executeUpdate() == 1) {
                logger.logError("Report has been successfully UPDATED");
            }
        ...

其中 getCLOB() 方法是:

private CLOB getCLOB(String xmlData, Connection conn) throws SQLException{
    CLOB tempClob = null;
    try{
        // If the temporary CLOB has not yet been created, create new
        tempClob = CLOB.createTemporary(conn, true, CLOB.DURATION_SESSION);

        // Open the temporary CLOB in readwrite mode to enable writing
        tempClob.open(CLOB.MODE_READWRITE);
        // Get the output stream to write
        Writer tempClobWriter = tempClob.getCharacterOutputStream();
        // Write the data into the temporary CLOB
        tempClobWriter.write(xmlData);

        // Flush and close the stream
        tempClobWriter.flush();
        tempClobWriter.close();

        // Close the temporary CLOB
        tempClob.close();
    } catch(SQLException sqlexp){
        tempClob.freeTemporary();
        sqlexp.printStackTrace();
    } catch(Exception exp){
        exp.printStackTrace();
        tempClob.freeTemporary();
        exp.printStackTrace();
    }
    return tempClob;
}

我也尝试通过传递 ((DelegatingConnection) conn).getInnermostDelegate() 连接,但没有用。

此外,我尝试了 Shiny已建议here .这次它在我选择数据时挂起。

我使用的是 Oracle 9i,JDBC Oracle Driver 版本高于 10(抱歉,现在不记得确切的版本)。

最佳答案

对于 Oracle JDBC 驱动程序,您不能使用 setClob()。它不会引发错误,但也不会起作用。这背后的原因是 JDBC 驱动程序将尝试读取 inside executeUpdate() 中的 Clob 流。因此,您必须在更新之前打开流,运行更新,然后之后关闭流。

因此,我总是使用select RPT_FILE ... for update,然后:

    ResultSet rs = null;
    try
    {
        rs = stmt.executeQuery ();
        rs.next ();

        Clob clob = rs.getClob (1);
        clob.truncate (0);
        clob.setString (1, data);
    }
    finally
    {
        rs = DBUtil.close (rs);
    }

您可以将 setString() 替换为将 CLOB 作为流读取/写入的方法。这始终有效并且不会泄漏游标(因为 Oracle 的 JDBC 驱动程序中存在错误)。

但关键始终是相同的:您必须从 Oracle 获得一个 CLOB 对象。永远不要尝试自己创建其中之一。

关于java - 无法使用 DBCP 连接更新 CLOB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1471470/

相关文章:

java - 无法从数据库检索数据,但当名称更改时我可以检索

sql-server - PySpark 1.5 和 MSSQL jdbc

java - 使用 PreparedStatement.RETURN_GENERATED_KEYS 时出现 SQLException

java - 在 jtable 中使用 jquery 的动态字段

sql - Oracle:带条件的全文搜索

java - 在 mule studio 上使用 java 组件从数据库检索数据

java.lang.AbstractMethodError : oracle. jdbc.driver.OraclePreparedStatementWrapper.setBinaryStream

sql - Oracle:SQL查询查找属于表的所有触发器?

java - 如何使用适用于 Java 的 Google 日历 API 删除我的 Google 日历上的 Activity ?

java - 重构时如何阻止 IDEA 重新格式化我的代码?