java - long - mybatis annotations
Pase y devuelva un objeto de matriz personalizado en ibatis y oracle en java (4)
Tienes que comenzar con una instancia personalizada de TypeHandler
. Preferiríamos implementar TypeHandlerCallback
más TypeHandlerCallback
, pero en este caso necesitamos acceso a la Connection
subyacente.
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();
}
...
}
Luego, para conectarlo a la configuración de 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>
¡Espero que esto ayude!
He buscado un buen ejemplo de esto, pero todavía no me he encontrado con ninguno. Quiero pasar una matriz de cadenas personalizada de Java a Oracle y viceversa, utilizando el marco de IBATIS. ¿Alguien tiene un buen enlace a un ejemplo? Estoy llamando procs almacenados de IBATIS.
Gracias
Intenta usar statement.getObject(i)
y luego convierte a una matriz.
Bueno, los chicos de la compañía descubrieron la solución : necesitas haber implementado los métodos getResult en tu typeHandler y proporcionar el atributo adicional jdbcTypeName = ORACLE_REAL_ARRAY_TYPE en tu mapeador
bsanders me dio un buen punto de partida: esto es lo que tuve que hacer para que funcione dentro del entorno 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);
}
}
Observe la conexión nativa que tuve que obtener, el descriptor que tuve que hacer, etc. Sin embargo, aunque puedo pasar cosas a la base de datos como una matriz de cadenas, no he podido averiguar por qué no recibo nada. Mi parámetro OUT (el getResult (declaración de CallableStatement, int i) arroja una excepción de puntero nulo, aunque estoy configurando el parámetro de salida en el plsql en la base de datos.
--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;
Así es como lo estoy accediendo:
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>
¿Algunas ideas?