Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

Groovy SQL Oracle Array Função/Procedimento Registro de Parâmetros de Saída


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