Question

I am using JDBCTemplate to create the connection pool and get java.lang.ClassCastException: org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to oracle.jdbc.OracleConnection


I was trying to pass a list of objects from Java to a procedure in Oracle using spring data extension package.


Steps followed
Created an array and struct in Oracle.
Array Created using:

DROP TYPE SCHEMA_NAME.TB_T_TYPE;

CREATE OR REPLACE TYPE SCHEMA_NAME.TB_T_TYPE is table of T_TYPE;
/

Struct Created using:

DROP TYPE SCHEMA_NAME.T_TYPE;

CREATE OR REPLACE TYPE SCHEMA_NAME.T_TYPE is object ( 
NAME VARCHAR2(100), 
ATTRIBUTE1 VARCHAR2(100),
ATTRIBUTE2 VARCHAR2(100) 
)
/


Created a Procedure in Schema Level:

CREATE OR REPLACE procedure SCHEMA_NAME.POPULATE_TABLE_TEST (example TB_T_TYPE) as 
type t_tb_seq is table of number; 
l_t_seq t_tb_seq := t_tb_seq(); 
begin 
for i in 1.. example.count loop 
l_t_seq.extend; 
select 1 into l_t_seq(i) from dual; 
end loop; 
forall i in 1.. example.count 
insert into TABLE_TEST(id,name,attribute1,attribute2) 
values (l_t_seq(i), 
treat(example(i) as T_TYPE).NAME,
treat(example(i) as T_TYPE).ATTRIBUTE1, 
treat(example(i) as T_TYPE).ATTRIBUTE2 
); 
end;
/


Java
1. Spring Context file: I added accessToUnderlyingConnectionAllowed = true

2. Created function in DAO impl:

private final String ORACLE_STRUCT = "SEATMGR.T_TYPE "; 
private final String ORACLE_ARRAY = "SEATMGR.TB_T_TYPE"; 

@SuppressWarnings("unchecked")
public void testingArray(List<SeatAssignmentDetails> assignmentDetails) throws Exception {
    SimpleJdbcCall simpleJdbcCall;
    try {
        List<TestObject> objects = new ArrayList<TestObject>();
        TestObject[]  testArray = new TestObject[assignmentDetails.size()];
        int i = 0;
        for (SeatAssignmentDetails seatAssignmentDetails : assignmentDetails) {
            TestObject obj = new TestObject();
            obj.setCity(seatAssignmentDetails.getCity());
            obj.setSite(seatAssignmentDetails.getSite());
            obj.setState(seatAssignmentDetails.getState());
            testArray[i] = obj;
            i++;
        }
        simpleJdbcCall = new SimpleJdbcCall(
                sspaDBConnection.getJDBCTemplate());
        StructMapper<TestObject> mapper = new BeanPropertyStructMapper<TestObject>();
        simpleJdbcCall
                //              .withCatalogName("pkg_SSEQ_queries")
                .withProcedureName("POPULATE_TABLE_TEST")
                .withoutProcedureColumnMetaDataAccess()
                .declareParameters(new SqlParameter("example",Types.ARRAY,ORACLE_ARRAY));
        simpleJdbcCall.execute(new MapSqlParameterSource().addValue(
                "example", new SqlStructArrayValue<TestObject>(
                        testArray, mapper,
                        ORACLE_STRUCT, ORACLE_ARRAY)));
    } catch (Exception e) {
        logger.error("Horrible errrrrrr",e);
    }
}


I have been reading that if you use regular procedure call without using SimpleJdbcCall you will be able to cast the Poolable connection created by JDBCTemplate to regular Oracle connection by using ((DelegatingConnection)conn).getInnermostDelegate(); in the connection passed to the array descriptor object.




Issue:
The above java function fails on the execute line by throwing this exception:
java.lang.ClassCastException: org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to oracle.jdbc.OracleConnection

Thanks in advance.
Sam.

No correct solution

OTHER TIPS

You are using a third-party connection pool to work with Oracle RDBMS. SqlStructArrayValue should work with OracleConnection. Therefore, you need to make unwrap the physical connection from your connection pool.

OracleConnection oconn = conn.unwrap(OracleConnection.class);

In this case, you need to extend SqlStructArrayValue and unwrap OracleConnection from your connection pool.

public class OracleSqlStructArrayValue<T> extends SqlStructArrayValue {

    public OracleSqlStructArrayValue(T[] values, StructMapper<T> mapper, String structTypeName) {
        super(values, mapper, structTypeName);
    }

    public OracleSqlStructArrayValue(T[] values, StructMapper<T> mapper, String structTypeName, String arrayTypeName) {
        super(values, mapper, structTypeName, arrayTypeName);
    }

    @Override
    protected Object createTypeValue(Connection conn, int sqlType, String typeName) throws SQLException {
        if (!conn.isWrapperFor(OracleConnection.class)) {
            throw new SQLFeatureNotSupportedException("Oracle types supports only OracleConnection");
        }

        OracleConnection oconn = conn.unwrap(OracleConnection.class);

        return super.createTypeValue(oconn, sqlType, typeName);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top