JBoss下CLOB.createTemporary抛出ClassCast的异常
错误用法: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;
}
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中还是有不少经验总结的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;
}
}