无法使用DBCP连接更新CLOB

时间:2009-09-24 12:45:05

标签: java oracle jdbc clob apache-commons-dbcp

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

早些时候,我使用this实现了连接池,它工作正常,但能够更新CLOB。我切换到DBCP因为我得到 java.sql.SQLException:ORA-01000:超出最大打开游标。我在所有DAO中检查了connection,resultSet,preparedStatement对象。所有 finally 块都关闭了这些游标。仍然面临这个错误,因此决定切换到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驱动程序版本大于10(抱歉,现在还记不清确切版本)。

3 个答案:

答案 0 :(得分:1)

您是否尝试过使用PreparedStatement.setClob方法代替setObject

答案 1 :(得分:1)

使用Oracle JDBC驱动程序,您无法使用setClob()。它不会抛出错误,但它也不起作用。这背后的原因是JDBC驱动程序将尝试读取 {/ 1}}内的Clob流。因此,您必须在更新之前打开流,运行更新,然后关闭流

因此,我总是使用executeUpdate(),然后使用:

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); } 以将CLOB读取/写为流。这总是有效并且不会泄漏游标(因为Oracle的JDBC驱动程序中存在错误)。

但是密钥总是一样的:你必须从Oracle获得一个CLOB对象。永远不要试图自己创造其中一个。

答案 2 :(得分:0)

OTN有一些documentation on clob handling in Oracle JDBC可能会有所帮助。