[ 
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

Reply via email to