错误用法:CLOB.createTemporary(conn,....);
正确用法:CLOB.createTemporary(((WrappedConnection) con).getUnderlyingConnection() ,.....);
原理:
=================================================================
if you are using jboss or any other AS that perform jdbc connection pooling , the classcast exception is caused by the "conn" object. (I had this problem using jboss4.0.1/oracle9.2).
In jboss4 the Connection object retrieved by ConnectionFactory.makeconnection() is an instance of org.jboss.resource.adapter.jdbc.WrappedConnection class (or a DelegatingConnection in tomcat or products that use DBCP)
=================================================================
include jboss-common-jdbc-wrapper.jar with WrappedConnection class
=============================《2008-9-10》=======================
最近看了看人家Spring,老早处理了这种情况了,具体见NativeJdbcExtractor接口
public interface NativeJdbcExtractor {
boolean isNativeConnectionNecessaryForNativeStatements();
boolean isNativeConnectionNecessaryForNativePreparedStatements();
boolean isNativeConnectionNecessaryForNativeCallableStatements();
//呵呵,就是这个方法
Connection getNativeConnection(Connection con) throws SQLException;
Connection getNativeConnectionFromStatement(Statement stmt) throws SQLException;
Statement getNativeStatement(Statement stmt) throws SQLException;
PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException;
CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException;
ResultSet getNativeResultSet(ResultSet rs) throws SQLException;
}
来看看,Jboss的特定实现:
public class JBossNativeJdbcExtractor extends NativeJdbcExtractorAdapter {
private static final String WRAPPED_CONNECTION_NAME = "org.jboss.resource.adapter.jdbc.WrappedConnection";
private static final String WRAPPED_STATEMENT_NAME = "org.jboss.resource.adapter.jdbc.WrappedStatement";
private static final String WRAPPED_RESULT_SET_NAME = "org.jboss.resource.adapter.jdbc.WrappedResultSet";
private Class wrappedConnectionClass;
private Class wrappedStatementClass;
private Method getUnderlyingConnectionMethod;
private Method getUnderlyingStatementMethod;
/**
* This constructor retrieves JBoss JDBC wrapper classes,
* so we can get the underlying vendor connection using reflection.
*/
public JBossNativeJdbcExtractor() {
try {
this.wrappedConnectionClass = getClass().getClassLoader().loadClass(WRAPPED_CONNECTION_NAME);
this.wrappedStatementClass = getClass().getClassLoader().loadClass(WRAPPED_STATEMENT_NAME);
this.getUnderlyingConnectionMethod =
this.wrappedConnectionClass.getMethod("getUnderlyingConnection", (Class[]) null);
this.getUnderlyingStatementMethod =
this.wrappedStatementClass.getMethod("getUnderlyingStatement", (Class[]) null);
}
catch (Exception ex) {
throw new DASEntityRuntimeException(ExceptionConstant.DAS_14101034,
"Could not initialize JBossNativeJdbcExtractor because JBoss API classes are not available",
ex);
}
}
/**
* Retrieve the Connection via JBoss' <code>getUnderlyingConnection</code> method.
*/
protected Connection doGetNativeConnection(Connection con) throws SQLException {
if (this.wrappedConnectionClass.isAssignableFrom(con.getClass())) {
try {
return (Connection) this.getUnderlyingConnectionMethod.invoke(con, (Object[]) null);
}
catch (InvocationTargetException ex) {
throw new DASEntityRuntimeException(ExceptionConstant.DAS_14101034,
"JBoss' getUnderlyingConnection method failed", ex
.getTargetException());
}
catch (Exception ex) {
throw new DASEntityRuntimeException(ExceptionConstant.DAS_14101034,
"Could not access JBoss' getUnderlyingConnection method",
ex);
}
}
return con;
}
/**
* Retrieve the Connection via JBoss' <code>getUnderlyingStatement</code> method.
*/
public Statement getNativeStatement(Statement stmt) throws SQLException {
if (this.wrappedStatementClass.isAssignableFrom(stmt.getClass())) {
try {
return (Statement) this.getUnderlyingStatementMethod.invoke(stmt, (Object[]) null);
}
catch (InvocationTargetException ex) {
throw new DASEntityRuntimeException(ExceptionConstant.DAS_14101034,
"JBoss' getUnderlyingStatement method failed", ex
.getTargetException());
}
catch (Exception ex) {
throw new DASEntityRuntimeException(ExceptionConstant.DAS_14101034,
"Could not access JBoss' getUnderlyingStatement method",
ex);
}
}
return stmt;
}
/**
* Retrieve the Connection via JBoss' <code>getUnderlyingStatement</code> method.
*/
public PreparedStatement getNativePreparedStatement(PreparedStatement ps) throws SQLException {
return (PreparedStatement) getNativeStatement(ps);
}
/**
* Retrieve the Connection via JBoss' <code>getUnderlyingStatement</code> method.
*/
public CallableStatement getNativeCallableStatement(CallableStatement cs) throws SQLException {
return (CallableStatement) getNativeStatement(cs);
}
/**
* Retrieve the Connection via JBoss' <code>getUnderlyingResultSet</code> method.
* <p>We access WrappedResultSet via direct reflection, since this class only
* appeared in JBoss 3.2.4 and we want to stay compatible with at least 3.2.2+.
*/
public ResultSet getNativeResultSet(ResultSet rs) throws SQLException {
if (rs.getClass().getName().equals(WRAPPED_RESULT_SET_NAME)) {
try {
Method getUnderlyingResultSetMethod = rs.getClass().getMethod("getUnderlyingResultSet", (Class[]) null);
return (ResultSet) getUnderlyingResultSetMethod.invoke(rs, (Object[]) null);
}
catch (InvocationTargetException ex) {
throw new DASEntityRuntimeException(ExceptionConstant.DAS_14101034,
"JBoss' getUnderlyingResultSet method failed", ex
.getTargetException());
}
catch (Exception ex) {
throw new DASEntityRuntimeException(ExceptionConstant.DAS_14101034,
"Could not access JBoss' getUnderlyingResultSet method",
ex);
}
}
return rs;
}
}
看来Spring中还是有不少经验总结的