



Вам нужно начать с кастомного экземпляра TypeHandler. Мы бы предпочли реализовать более простой TypeHandlerCallback, но в этом сценарии нам нужен доступ к базовому Connection.
public class ArrayTypeHandler implements TypeHandler {
public void setParameter(PreparedStatement ps, int i, Object param, String jdbcType)
throws SQLException {
if (param == null) {
ps.setNull(i, Types.ARRAY);
} else {
Connection conn = ps.getConnection();
Array loc = conn.createArrayOf("myArrayType", (Object[]) param);
ps.setArray(i, loc);
}
}
public Object getResult(CallableStatement statement, int i)
throws SQLException {
return statement.getArray(i).getArray();
}
...
}
Затем, чтобы подключить его в конфигурации iBATIS:
<?xml version = "1.0"?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace = "arrayTest">
<parameterMap id = "storedprocParams" class = "map">
<parameter property = "result" mode = "OUT" jdbcType = "ARRAY" typeHandler = "ArrayTypeHandler"/>
<parameter property = "argument" mode = "IN" jdbcType = "ARRAY" typeHandler = "ArrayTypeHandler"/>
</parameterMap>
<procedure id = "storedproc" parameterMap = "arrayTest.storedprocParams">
{? = call My_Array_Function( ? )}
</procedure>
</sqlMap>
Надеюсь это поможет!
Это было хорошей отправной точкой - мне нужно было получить собственное соединение от RAD, добавить дескриптор, описывающий мой настраиваемый массив, и убедиться, что объект в базе данных доступен. Посмотрите, что я сделал в ответ.
bsanders дал мне хорошую отправную точку - вот что мне нужно было сделать, чтобы заставить его работать в среде RAD (websphere 6.2).
public Object getResult(CallableStatement statement, int i) throws SQLException {
return statement.getArray(i).getArray(); //getting null pointer exception here
}
public void setParameter(PreparedStatement ps, int i, Object param, String jdbcType) throws SQLException {
if (param == null) {
ps.setNull(i, Types.ARRAY);
} else {
String[] a = (String[]) param;
//ARRAY aOracle = ARRAY.toARRAY(a, (OracleConnection)ps.getConnection());
//com.ibm.ws.rsadapter.jdbc.WSJdbcConnection
w = (com.ibm.ws.rsadapter.jdbc.WSJdbcConnection)ps.getConnection());
//com.ibm.ws.rsadapter.jdbc.WSJdbcObject x;
Connection nativeConnection = Connection)WSJdbcUtil.getNativeConnection((WSJdbcConnection)ps.getConnection());
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("F2_LIST", nativeConnection);
ARRAY dataArray = new ARRAY(descriptor, nativeConnection, a);
ps.setArray(i, dataArray);
}
}
Обратите внимание на nativeConnection, который мне нужно было получить, дескриптор, который мне нужно было создать, и так далее. Однако, хотя я могу передавать данные в базу данных в виде массива строк, я не мог понять, почему я ничего не получаю обратно. Мой параметр OUT (getResult (CallableStatement statment, int i) выдает исключение с нулевым указателем, хотя я устанавливаю параметр out в plsql в базе данных.
--stored procedure to take a | delimited ids
PROCEDURE array_test (argument IN f2_list, result OUT f2_list)
AS
l_procname_v VARCHAR2 (50) := 'array_test';
l_param_list VARCHAR2 (2000)
:= l_procname_v || ' param_values: p_string: ';
p_status_n NUMBER;
p_message_v VARCHAR2 (2000);
ret_list f2_list := new f2_list();
l_count_v varchar2(200);
BEGIN
l_count_v := argument.COUNT;
for x in 1..argument.count
LOOP
pkg_az_common_util.az_debug (package_nm,
l_procname_v,
pkg_az_data_type_def.debug_num,
argument(x)
);
end loop;
pkg_az_common_util.az_debug (package_nm,
l_procname_v,
pkg_az_data_type_def.debug_num,
l_count_v
);
ret_list.extend();
ret_list(1) := 'W';
ret_list.extend();
ret_list(2) := 'X';
ret_list.extend();
ret_list(3) := 'Y';
ret_list.extend();
ret_list(4) := 'Z';
result := ret_list;
EXCEPTION
WHEN OTHERS
THEN
p_status_n := pkg_az_common_util.get_error_code;
p_message_v :=
TO_CHAR (p_status_n)
|| '|'
|| 'Oracle Internal Exception('
|| l_procname_v
|| ')'
|| '|'
|| TO_CHAR (SQLCODE)
|| '|'
|| SQLERRM
|| l_param_list;
standard_pkg.log_error (package_nm,
l_procname_v,
SQLCODE,
p_message_v
);
IF p_status_n = 1
THEN
RAISE;
END IF;
END array_test;
Вот как я получаю к нему доступ:
Map queryParamsTest = new HashMap();
String[] testArray = {"A", "B", "C"};
queryParamsTest.put("argument", testArray);
DaoUtils.executeQuery(super.getSqlMapClientTemplate(),
"arrayTest", queryParamsTest, queryParamsTest
.toString()); //just executes query
String[] resultArray = (String[])queryParamsTest.get("result");
for(int x = 0; x< resultArray.length; x++)
{
System.out.println("Result: " + resultArray[x]);
}
<parameterMap id = "storedprocParams" class = "map">
<parameter property = "argument" mode = "IN" jdbcType = "ARRAY" typeHandler = "ArrayTypeHandler"/>
<parameter property = "result" mode = "OUT" jdbcType = "ARRAY" typeHandler = "ArrayTypeHandler"/>
</parameterMap>
<procedure id = "arrayTest" parameterMap = "storedprocParams">
{call pkg_az_basic_dev.array_test(?, ? )}
</procedure>
Есть идеи?
Попробуйте использовать statement.getObject(i), а затем выполнить приведение к массиву.
Что ж, ребята в компании обнаружили решение: вам необходимо реализовать метод (ы) getResult в вашем typeHandler и предоставить дополнительный атрибут jdbcTypeName = ORACLE_REAL_ARRAY_TYPE в вашем картографе
я заметил, что тип ARRAY не поддерживается в документации batis, я обнаружил, что это дезинформативно
что вы имеете в виду под строковым массивом обычай, он чем-то отличается от String []?