2011-07-01 23 views
10

Mi objetivo es en realidad volcar todos los datos de una base de datos en un archivo XML. La base de datos no es demasiado grande, es de unos 300 MB. El problema es que tengo una limitación de memoria de 256 MB (solo en JVM). Entonces, obviamente, no puedo leer todo en la memoria.Manejo de gran cantidad de datos en MyBatis

me las arreglé para resolver este problema utilizando iBatis (sí quiero decir iBatis, no mybatis) llamando es getList(... int skip, int max) varias veces, con skip incrementado. Eso soluciona mi problema de memoria, pero no estoy impresionado con la velocidad. Los nombres de variables sugieren que lo que el método hace bajo el capó es leer todo el salto del conjunto de resultados y luego el registro especificado. Esto me suena bastante redundante (no estoy diciendo que eso sea lo que está haciendo el método, solo estoy adivinando la base del nombre de la variable).

Ahora, cambié a myBatis 3 para la próxima versión de mi aplicación. Mi pregunta es: ¿hay alguna forma mejor de manejar una gran cantidad de fragmentos de datos por partes en myBatis? ¿Hay alguna forma de hacer que myBatis procese los primeros N registros, devolverlos a la persona que llama mientras se mantiene abierta la conexión del conjunto de resultados para que la próxima vez que el usuario llame al getList (...) comience a leer desde el registro N + 1 sin hacer ningún "salto a la comba"?

Respuesta

7

No, mybatis no tiene capacidad completa para transmitir los resultados aún.

EDIT 1: Si usted no necesita ResultMap anidados entonces se podría implementar un control de resultados a medida para transmitir los resultados. en las versiones actuales de MyBatis. (3.1.1) La limitación actual es cuando necesita hacer un mapeo complejo de resultados. NestedResultSetHandler no permite manejadores de resultados personalizados. Hay una solución disponible, y parece que actualmente está destinada a 3.2. Ver Issue 577.

En resumen, para transmitir grandes conjuntos de resultados utilizando MyBatis necesitará.

  1. Implement your own ResultSetHandler.
  2. Aumenta el tamaño de búsqueda. (como se indica más abajo por Guillaume Perrot)
  3. Para los mapas de resultados anidados, utilice el arreglo discutido en Issue 577. Esta solución también resuelve algunos problemas de memoria con grandes conjuntos de resultados.
16

myBatis CAN stream results. Lo que necesita es un controlador de resultados personalizado. Con esto, puede tomar cada fila por separado y escribirla en su archivo XML. El esquema general es el siguiente:

session.select(
    "mappedStatementThatFindsYourObjects", 
    parametersForStatement, 
    resultHandler); 

Dónde ResultHandler es una instancia de una clase que implementa la interfaz ResultHandler. Esta interfaz tiene solo un método handleResult. Este método le proporciona un objeto ResultContext. Desde este contexto, puede recuperar la fila que se está leyendo actualmente y hacer algo con ella.

handleResult(ResultContext context) { 
    Object result = context.getResultObject(); 
    doSomething(result); 
} 
+8

Su respuesta carece de un detalle importante: necesita agregar @Options (fetchSize = Integer.MIN_VALUE) (o el equivalente XML) a su extracto. Y no funcionaba en MyBatis 3.0.5 (Lo comprobé con Eclipse Memory Analyzer). Actualicé a MyBatis 3.1.1 y ahora la transmisión funciona correctamente. –

2

handleResult recibe tantos registros como obtiene la consulta, sin pausa.

Cuando hay demasiados registros para procesar utilicé sqlSessionFactory.getSession(). GetConnection(). Luego, como JDBC normal, obtenga una Declaración, obtenga el Conjunto de resultados y procese uno a uno los registros. No te olvides de cerrar la sesión.

0

Si acaba de eliminar todos los datos sin ningún requisito de ordenamiento de las tablas, ¿por qué no hacer directamente la paginación en SQL?Establezca un límite para la instrucción de consulta, donde se especifique una identificación de registro diferente como desplazamiento, para separar toda la tabla en fragmentos, cada uno de los cuales podría leerse directamente en la memoria si el límite de filas es un número razonable.

El SQL podría ser algo como:

SELECT * FROM resource 
    WHERE "ID" >= continuation_id LIMIT 300; 

Creo que esto podría ser visto como una solución alternativa para que usted pueda volcar todos los datos por trozos, deshacerse de los diferentes problemas de entidad en mybatis, o cualquier Capa de persistencia, soporte.

Cuestiones relacionadas