views:

427

answers:

3

Am trying to do update a clob column using a connection object that is retrieved using Apache DBCP connection pooling.

Earlier, I've implemented connection pooling using this and it was working fine i.e am able to update CLOB. I switched to DBCP because I was getting java.sql.SQLException: ORA-01000: maximum open cursors exceeded. I've checked connection, resultSet, preparedStatement objects in all the DAOs. All the finally blocks have these cursors closed. Still am facing this error and so decided to switch to DBCP.

But, when I try to update CLOB, with this DBCP connection, the application just hangs at 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");
      }
     ...

where getCLOB() method is:

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;
}

I've also tried by passing the ((DelegatingConnection) conn).getInnermostDelegate() connection, but no use.

Also, I tried what Shiny has suggested here. This time its hanging while I'm selecting the data.

Am using Oracle 9i and the JDBC Oracle Driver version is above 10(Sorry, couldn't remember exact version now).

+1  A: 

Hi cedar715,

have you tried using the PreparedStatement.setClob method instead of setObject ?

Vincent Malgrat
A: 

OTN has some documentation on clob handling in Oracle JDBC that may be helpful.

jsight
+1  A: 

With the Oracle JDBC driver, you can't use setClob(). It won't throw an error but it also won't work. The reason behind this is that the JDBC driver will try to read your Clob stream inside the executeUpdate(). So you must open the stream before the update, run the update and then close the stream afterwards.

Therefore, I always use select RPT_FILE ... for update, and then:

    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);
    }

You can replace setString() with the methods to read/write the CLOB as a stream. That always works and doesn't leak cursors (because of bugs in Oracle's JDBC driver).

But the key is always the same: You must get a CLOB object from Oracle. Never try to create one of them yourself.

Aaron Digulla