2009-09-24 7 views
2

Je tente de mettre à jour une colonne clob à l'aide d'un objet de connexion récupéré à l'aide du pool de connexions Apache DBCP. Plus tôt, j'ai mis en place la mise en commun de connexion en utilisant this et il fonctionnait bien, je suis capable de mettre à jour CLOB. Je suis passé à DBCP parce que je recevais java.sql.SQLException: ORA-01000: les curseurs ouverts maximum dépassé. J'ai vérifié les objets connection, resultSet, preparedStatement dans tous les DAO. Tous les blocs ont ces curseurs fermés. Je suis toujours confronté à cette erreur et j'ai donc décidé de passer à DBCP. Mais, quand j'essaye de mettre à jour CLOB, avec cette connexion DBCP, l'application se bloque juste à pstmt.executeUpdate().impossible de mettre à jour CLOB à l'aide de la connexion DBCP

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

où la méthode getCLOB() est:

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

J'ai aussi essayé en passant la connexion ((DelegatingConnection) conn).getInnermostDelegate(), mais aucune utilisation. En outre, j'ai essayé ce que Shiny a suggéré here. Cette fois, c'est suspendu pendant que je sélectionne les données. J'utilise Oracle 9i et la version du pilote Oracle JDBC est supérieure à 10 (Désolé, je ne me souviens plus de la version exacte maintenant).

+0

Pourriez-vous montrer votre méthode getCLOB (et quel type de données est "xmlReport"?)? – jsight

Répondre

1

Avec le pilote Oracle JDBC, vous ne pouvez pas utiliser setClob(). Cela ne va pas jeter une erreur mais ça ne marchera pas non plus. La raison derrière cela est que le pilote JDBC va essayer de lire votre flux Clob à l'intérieur le executeUpdate(). Vous devez donc ouvrir le flux avant la mise à jour, exécuter la mise à jour, puis fermer le flux ensuite.

Par conséquent, j'utilise toujours select RPT_FILE ... for update, puis:

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

Vous pouvez remplacer setString() les méthodes pour lire/écrire le CLOB en tant que flux. Cela fonctionne toujours et ne fuit pas les curseurs (à cause de bugs dans le pilote JDBC d'Oracle).

Mais la clé est toujours la même: vous devez obtenir un objet CLOB d'Oracle. N'essayez jamais de créer l'un d'eux vous-même.

1

avez-vous essayé d'utiliser la méthode PreparedStatement.setClob au lieu de setObject?