java - queryforlist - spring jdbc example
Soporte Spring JDBC y gran conjunto de datos (5)
Cuando utilizo uno de los diversos métodos de plantilla JDBC, estoy confundido sobre cómo iterar / desplazarse por grandes conjuntos de resultados (que no caben en la memoria). Incluso sin una exposición directa de una interfaz de Iterable, al menos esperaría que se invocaran instancias de RowCallbackHandler mientras la consulta no se ejecuta después de que se haya completado (o el almacenamiento en exceso).
Eché un vistazo a this (que no cambió nada para mí a pesar de ser similar en espíritu a este post en el desbordamiento de pila) y en this post en los foros de primavera. El último parece sugerir que el manejador de devolución de llamada debería ser llamado mientras el cursor está buscando datos. Sin embargo, mis pruebas no muestran tal comportamiento.
La base de datos es un Oracle10g. Estoy usando el controlador 11.1.0.7.0-Production y Spring 2.5.6.SEC01. ¿Alguna idea sobre cómo iterar sobre los conjuntos de resultados, preferiblemente manteniendo la lógica de mapeo de RowMapper, etc.?
- Cree un procedimiento almacenado personalizado que extienda
StoredProcedure
- Cree un
RowCallBackHandler
que pueda manejar cada fila, una a la vez. - Declara tus parámetros. Si tiene un conjunto de resultados, declare ese primero. Use la clase
SqlReturnResultSet
yRowCallBackHandler
usando suRowCallBackHandler
- Declara cualesquiera otros parámetros.
- Compilar
- Hice los pasos 2 a 5 en el constructor de mi procedimiento almacenado de cliente
- Crea un Mapa que contiene tus parámetros de entrada
- Ejecute sus procedimientos almacenados con los parámetros de entrada
Yo proporcionaría el código, pero el siguiente artículo contiene toda esta información.
Cómo llamar a procedimientos almacenados con plantillas Spring JDBC
Aquí hay una buena biblioteca para juntar todos los resultados de java sql en la memoria.
http://casperdatasets.googlecode.com
puede desplazarse / iterar a través del conjunto de datos, puede emitir consultas en su contra y crear índices para la optimización. también implementa la interfaz java.sql.resultset para que pueda continuar operando en los resultados de este conjunto de datos con cambios mínimos en su código jdbc.
Es una propiedad del controlador / conexión, ya sea transmitirle los datos o enviarlos de nuevo en una porción. Por ejemplo, en SQL Server, usa la propiedad SelectMethod
en la URL de conexión:
jdbc:microsoft:sqlserver://gsasql03:1433;DatabaseName=my_db;SelectMethod=direct
El valor de direct
significa que los resultados deben venir de una sola vez. La otra opción es el cursor
, que le permite especificar que desea que la conexión le envíe los resultados. No estoy seguro de cuál es el análogo para una fuente de datos de Oracle , me temo
El RowCallbackHandler
ciertamente funciona para mí.
Puede utilizar la biblioteca springjdbc-iterable :
CloseableIterator<MyObj> iter = jt.queryForIter("select ...", params, mapper);
El iterador se cerrará automáticamente al agotarse o se puede cerrar manualmente. Funcionará solo dentro de los límites de la transacción.
Descargo de responsabilidad: escribí esta biblioteca
El controlador JDBC de Oracle tiene el soporte adecuado para el método setFetchSize()
en java.sql.Statement
, que le permite controlar cuántas filas recuperará el controlador de una sola vez.
Sin embargo, RowMapper
, RowMapper
como lo utiliza Spring, lee cada fila en la memoria, hace que RowMapper
traduzca en un objeto y almacene el objeto de cada fila en una gran lista. Si su conjunto de resultados es enorme, entonces esta lista se volverá grande, independientemente de cómo JDBC obtenga los datos de la fila.
Si necesita manejar grandes conjuntos de resultados, entonces RowMapper no es escalable. Podría considerar usar RowCallbackHandler
en RowCallbackHandler
lugar, junto con los métodos correspondientes en JdbcTemplate. RowCallbackHandler
no dicta cómo se almacenan los resultados, dejando que usted los almacene.