1、在数据库中新建一个数组:
create or replace type number_array as varray(10) of int
2、传入数组:
createDescriptor()第一个参数为第1步中创建的type的名字,即:NUMBER_ARRAY,请务必大写,否则将报“无效的名称模式”错误。
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("NUMBER_ARRAY", conn); //标注1
preparedstatement.setArray(parameterIndex++, new ARRAY(descriptor,conn,company.getTypeIds())); //标注2
以上方法只能在没有使用连接池时使用,如果采用了连接池进行管理数据库连接,在执行如上代码时将会报如下错误:
org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to oracle.jdbc.OracleConnection
原因:使用连接池的情况下,Connection对象不是在BasicDataSource中实例化
public Connection getConnection()
throws SQLException
{
return createDataSource().getConnection();//createDataSource()中加载配置的driverClassName类
}
,而是在PoolingDataSource中被覆盖
public Connection getConnection()
throws SQLException
{
try
{
Connection conn = (Connection)this._pool.borrowObject();
if (conn != null) {
conn = new PoolGuardConnectionWrapper(conn);
}
return conn;
} catch (SQLException e) {
throw e;
} catch (NoSuchElementException e) {
throw new SQLNestedException("Cannot get a connection, pool error " + e.getMessage(), e);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new SQLNestedException("Cannot get a connection, general error", e);
}
}
注意粗体部分,可见返回的connection对象被包装成PoolGuardConnectionWrapper内部类。
可以执行
System.out.println("================"+conn.getClass().getName());进行查验。将输出org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper
而在“标注1”处,传入的connection需要被强制转换为oracle.jdbc.OracleConnection,由于无法转换成功,故报错。
public static ArrayDescriptor createDescriptor(String paramString, Connection paramConnection, boolean paramBoolean1, boolean paramBoolean2)
throws SQLException
{
if ((paramString == null) || (paramString.length() == 0) || (paramConnection == null))
{
DatabaseError.throwSqlException(null, 60, "ArrayDescriptor.createDescriptor: Invalid argument,'name' should not be an empty string and 'conn' should not be null.");
}
SQLName localSQLName = new SQLName(paramString, (oracle.jdbc.OracleConnection)paramConnection);
return createDescriptor(localSQLName, paramConnection);
}
因此,使用连接池时,需要在“标注1”、“标注2”处传入一个可以转换为OracleConnection的类。
解决方法:从PoolGuardConnectionWrapper获取原始连接。
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("NUMBER_ARRAY", conn.getMetaData().getConnection());
preparedstatement.setArray(parameterIndex++, new ARRAY(descriptor,conn.getMetaData().getConnection(),company.getTypeIds()));
3、执行存储过程语句,并保证存储过程中的数组参数类型为第1步中创建的类型。