मुझे अभी एक ही समस्या का सामना करना पड़ा है और अब एक समाधान है। मूल रूप से दो समस्याएं हैं। पहला यह है कि आउटपुट पैरामीटर पंजीकृत होने पर ओरेकल को आपको सरणी प्रकार का नाम बताने की आवश्यकता होती है। दूसरा यह है कि ग्रोवी को आपको ऐसा करने के लिए कैसे राजी किया जाए। सौभाग्य से, ऐसा प्रतीत होता है कि ग्रोवी डिजाइनरों ने इसके बारे में सोचा और आपको groovy.sql.Sql को उप-वर्ग में पैरामीटर सेटिंग में शामिल करने की अनुमति दी।
मैं इस उत्तर में 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
अब हमें कुछ नई ग्रोवी कक्षाओं की आवश्यकता है:
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)
}
}
}
इनका उपयोग बहुत सीधा है। आप शायद परिणामी डेटा संरचनाओं को समझने के लिए सरणियों पर Oracle दस्तावेज़ीकरण चाहते हैं।
// 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
}
}