Acabei de enfrentar o mesmo problema e agora tenho uma solução. Basicamente, existem dois problemas. A primeira é que o Oracle exige que você informe o nome do tipo de array quando o parâmetro de saída for registrado. A segunda é como persuadir Groovy a deixar você fazer isso. Felizmente, parece que os designers do Groovy pensaram nisso e permitem que você subclassifique groovy.sql.Sql para se conectar à configuração do parâmetro.
Usarei o tipo de exemplo e o procedimento armazenado nesta resposta para uma pergunta semelhante no nível do JDBC:
SQL> CREATE TYPE t_type AS OBJECT (val VARCHAR(4));
2 /
Type created
SQL> CREATE TYPE t_table AS TABLE OF t_type;
2 /
Type created
SQL> CREATE OR REPLACE PROCEDURE p_sql_type (p_out OUT t_table) IS
2 BEGIN
3 p_out := t_table(t_type('a'), t_type('b'));
4 END;
5 /
Procedure created
Agora precisamos de algumas novas classes Groovy:
import groovy.sql.*
import java.sql.CallableStatement
import java.sql.PreparedStatement
import java.sql.SQLException
import oracle.jdbc.driver.*
class OracleArrayOutParameter implements OutParameter {
String typeName
int getType() {
OracleTypes.ARRAY
}
}
class OracleArrayAwareSql extends Sql {
OracleArrayAwareSql(Sql parent) {
super(parent)
}
void setObject(PreparedStatement statement, int i, Object value) throws SQLException {
if (value instanceof OracleArrayOutParameter) {
try {
OracleArrayOutParameter out = (OracleArrayOutParameter) value;
((CallableStatement) statement).registerOutParameter(i, out.getType(), out.typeName);
} catch (ClassCastException e) {
throw new SQLException("Cannot register out parameter.");
}
}
else {
super.setObject(statement, i, value)
}
}
}
O uso destes é bastante simples. Você provavelmente desejará que a documentação do Oracle sobre arrays entenda as estruturas de dados resultantes.
// First create a "normal" groovysqlSql instance, using whatever method you like
def parent = Sql.newInstance("jdbc:oracle:thin:@host:port:sid", "user", "password", "oracle.jdbc.OracleDriver")
// Then create an OracleArrayAwareSql instance giving that parent instance as a parameter
def sql = new OracleArrayAwareSql(parent)
// Now define an OracleArrayOutParameter naming the array type
def tTableParam = new OracleArrayOutParameter(typeName: 'T_TABLE')
// And make a stored procedure call as usual
sql.call("{call p_sql_type(${tTableParam})}") { out ->
// The returned parameter is of type oracle.sql.ARRAY
out.array.each { struct ->
println struct.attributes
}
}