sql >> Base de Datos >  >> RDS >> Oracle

Groovy SQL Oracle Array Function/Procedure Out Parámetros Registro

Acabo de enfrentar el mismo problema y ahora tengo una solución. Básicamente hay dos problemas. La primera es que Oracle requiere que le diga el nombre del tipo de matriz cuando se registra el parámetro de salida. El segundo es cómo persuadir a Groovy para que te deje hacer eso. Afortunadamente, parece que los diseñadores de Groovy pensaron en esto y le permiten crear una subclase de groovy.sql.Sql para conectarse a la configuración de parámetros.

Usaré el tipo de ejemplo y el procedimiento almacenado en esta respuesta a una pregunta similar en el nivel de 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

Ahora necesitamos un par de clases Groovy nuevas:

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

El uso de estos es bastante sencillo. Probablemente querrá consultar la documentación de Oracle sobre arreglos para comprender las estructuras de datos 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
    }
}