[
http://issues.apache.org/jira/browse/IBATIS-145?page=comments#action_12331807 ]
ING IKRS commented on IBATIS-145:
---------------------------------
I was able to use user-defined types with stored procedures after making a
minor modification (I made JdbcTypeRegistry.setType public) to the iBatis
source downloaded beginning of September'05.
Below I include full description of my test code.
hi,
I was able to use iBatis to call stored procedures with array arguments, e.g.
PS_VARCHAR_ARRAY_TYPE, after making only a minimal hack to the iBatis code.
My test stored procedure was:
/* prefixes prefix to all items in p_str_a and returns them in o_str_a */
PROCEDURE prefix( p_prefix IN VARCHAR2,
p_str_a IN PS_VARCHAR2_ARRAY_TYPE,
o_str_a OUT PS_VARCHAR2_ARRAY_TYPE);
The sql mapping in xml file was
<parameterMap id="prefixStringsParams" class="map" >
<parameter property="prefix" jdbcType="VARCHAR2" javaType="java.lang.String"
mode="IN"/>
<parameter property="stringArray" jdbcType="PS_VARCHAR2_ARRAY_TYPE"
typeName="PS_VARCHAR2_ARRAY_TYPE" typeHandler="StringArrayHandler" mode="IN"/>
<parameter property="prefixedStringArray" jdbcType="PS_VARCHAR2_ARRAY_TYPE"
typeName="PS_VARCHAR2_ARRAY_TYPE" typeHandler="StringArrayHandler" mode="OUT"/>
</parameterMap>
<procedure id="prefixStrings" parameterMap="prefixStringsParams" >
{call TEST_IBATIS.prefix (?, ?, ?)}
</procedure>
In order to handle PS_VARCHAR2_ARRAY_TYPE I had to implement Custom TypeHandler
public class StringArrayTypeHandlerCallback implements TypeHandlerCallback {
static{
JdbcTypeRegistry.setType("PS_VARCHAR2_ARRAY_TYPE", Types.ARRAY); <<== here is
where the hack was needed -- the setType method was private in JdbcTypeRegistry
and I had to make it public in order to tell it that PS_VARCHAR2_ARRAY_TYPE
corresponds to Types.ARRAY, otherwise I would get an exception
};
public void setParameter(ParameterSetter setter, Object parameter)
throws SQLException {
String[] strArr = (String[])parameter;
setter.getPreparedStatement().getConnection();
Connection conn = setter.getPreparedStatement().getConnection();
ArrayDescriptor stringArrayDescriptor =
ArrayDescriptor.createDescriptor("PS_VARCHAR2_ARRAY_TYPE", conn);
ARRAY valArray;
try {
valArray = new ARRAY(stringArrayDescriptor, conn, strArr);
} catch (SQLException e) {
throw e;
}
setter.setArray(valArray);
}
public Object getResult(ResultGetter getter) throws SQLException {
Array arr = getter.getArray();
if(arr==null)
return null;
else
return (String[])arr.getArray();
}
public Object valueOf(String arg0) {
String[] r = new String[1];
r[0] = arg0;
return r;
}
}
The handler had to be registered in the main ibatis config file:
<typeAlias alias="StringArrayHandler"
type="com.ingenuity.dbcommon.ibatis.StringArrayTypeHandlerCallback" />
<typeHandler javaType="[Ljava.lang.String;" callback="StringArrayHandler" />
The test code was this:
String resource = "com/ingenuity/dbcommon/ibatis/SqlMapConfig.xml";
Reader reader = Resources.getResourceAsReader(resource);
SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
Map dto = new HashMap();
dto.put("prefix", "pre-");
dto.put("stringArray", new String[]{"abc","cde"});
dto.put("prefixedStringArray", new String[]{});
printDto(dto);
sqlMap.update("prefixStrings", dto);
printDto(dto);
And the output was
prefix -> pre-
stringArray -> [abc, cde]
prefixedStringArray -> []
08:58:38.441 [main] DEBUG SimpleDataSource: Created connection 597230.
08:58:38.441 [main] DEBUG Connection: {conn-100000} Connection
08:58:38.631 [main] DEBUG PreparedStatement: {pstm-100001} PreparedStatement:
{call TEST_IBATIS.prefix (?, ?, ?)}
08:58:38.641 [main] DEBUG PreparedStatement: {pstm-100001} Parameters: [pre-,
[EMAIL PROTECTED]
08:58:38.641 [main] DEBUG PreparedStatement: {pstm-100001} Types:
[java.lang.String, oracle.sql.ARRAY]
08:58:38.661 [main] DEBUG SimpleDataSource: Returned connection 597230 to pool.
prefix -> pre-
stringArray -> [abc, cde]
prefixedStringArray -> [pre-abc, pre-cde]
As you can see the strings indeed got prefixed.
> oracle's user-defined objects are not supported as store procedure out
> parameters
> ---------------------------------------------------------------------------------
>
> Key: IBATIS-145
> URL: http://issues.apache.org/jira/browse/IBATIS-145
> Project: iBatis for Java
> Type: Improvement
> Components: SQL Maps
> Versions: 2.1.0
> Environment: oracle and maybe any others db that support user defined data
> types
> Reporter: ppz4j
> Assignee: Brandon Goodin
>
> we have to call legacy oracle store procedure with named array types as
> output parameters. When I try it I get an invalid parameter type exception
> This problem arises because to use these params the SQLExecutor class should
> call the ?callableStatement.registerOutputParameters? method version with
> the typeName param. In fact the java doc of this method suggests "This
> version of the method registerOutParameter should be used for a user-defined
> or REF output parameter" and "To be portable, however, applications should
> always provide these values for user-defined and REF parameters. Although it
> is intended for user-defined and REF parameters, this method may be used to
> register a parameter of any JDBC type. If the parameter does not have a
> user-defined or REF type, the typeName parameter is ignored "
> To handle this problem I have made some changes in source code and dtd file,
> but I hope that in a next version this problem will be resolved.
>
> Following the changes that I have made to add this enhancement:
> Added property typeName to bean BasicParameterMapping, with set and get
> methods.
> Added code that load typeName param from xml in SqlMapParser and code that
> save it as property of the current instance of mapping.
> Changed the SQLExecutor, now before call the
> CallableStatement.registerOutputParameter the registerOutputParameters method
> checks if the typeName of the given map parameter is not null. If it so it
> calls the overloaded method registerOutParameter(int paramIndex,int
> sqlType,String typeName) instead of registerOutParameter(int paramIndex,int
> sqlType.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira