SqlStructArrayValue:将对象列表传递给Oracle storedprocedure中的结构数组

时间:2014-02-28 19:07:32

标签: arrays oracle struct spring-data procedure

我使用JDBCTemplate创建连接池并获取java.lang.ClassCastException: org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to oracle.jdbc.OracleConnection


我试图使用spring数据扩展包将Java中的对象列表传递给Oracle中的过程。


遵循的步骤
在Oracle中创建了一个数组和结构 使用创建的数组:

DROP TYPE SCHEMA_NAME.TB_T_TYPE;

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

使用创建的结构:

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) 
)
/


架构级别中创建了一个程序

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


爪哇
 1. Spring Context文件:我添加了accessToUnderlyingConnectionAllowed = true

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


我一直在阅读如果你在不使用SimpleJdbcCall的情况下使用常规过程调用,你将能够使用((DelegatingConnection)conn)将JDBCTemplate创建的Poolable连接转换为常规Oracle连接.getInnermostDelegate(); 在传递给数组描述符对象的连接中。




问题
抛出此异常,上述java函数在执行行上失败:
java.lang.ClassCastException: org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to oracle.jdbc.OracleConnection

提前致谢。
萨姆。

1 个答案:

答案 0 :(得分:0)

您正在使用第三方连接池来使用Oracle RDBMS。 SqlStructArrayValue应该和OracleConnection一起使用。 因此,您需要从连接池中取消物理连接。

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

在这种情况下,您需要扩展SqlStructArrayValue并从连接池中解包OracleConnection

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