我正在尝试使用使用 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/