style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">

Problema al leer miles de registro con Hibernate

Hola !

Tengo la necesidad de leer tablas con 20 o mas millones de registros.

Cuando lanzo una consulta y me devuelve pocos registro no hay problema,
el problema viene cuando me devuelve unos cuantos miles de registros, me
da una excepción por problemas de memoria.

He estado leyendo cosas por internet pero no acabo de enterarme, temas
de paginación etc.

Para recibir la información que es mejor listas, map, colecciones etc.

Un Saludo

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de rj@vasso

Te recomiendo

Algunas ocaciones que me han tocado obtener miles de datos desde una base de datos , he tenido que conciderar utilizar en hibernate hacer el query de la siguiente manera la cual nosotros le llamamos hacer querys nativos

List<Object[]> result = new ArrayList<Object[]>();
                Query query;
                try{
                        query = getSession().createSQLQuery(sentSQL);
                        System.out.println(query.toString());
                        if(!(query.list().isEmpty())){
                                result = query.list();
                        }
                }catch (Exception e) {
                        // TODO: handle exception
                        System.out.println("Error: " + e.getLocalizedMessage() + " : " + e.getMessage() + " : " + e.getStackTrace());
                }

de esta manera te regresa una lista de arreglo de objetos y te da el dinamismo de recuperarlo segun sea el orden de tu consulta .. y posteriormente ya poderlo colocar en el objeto correpondiente.

otra opcion es tener cuidado con la propiedad de hibernate "lazy".. pero te recomiendo esta manera del ejemplo ya que jdbc puro es mucho mas rapido para consulta informacion masiva en una DB.

aunque si con esto no lo puedes resolver y realmente son millones , podrias delimitar la consulta en cuestion de registros y pasarlo por lotes ...

Saludos

Imagen de neko069

Pues en mi opinión, me iría

Pues en mi opinión, me iría más por el lado de JDBC para hacer una consulta que devuelva muchos datos, desaconsejaría el uso de Hibernate por aquéllo de que es más lento en cargas fuertes.
Checa éste tutorial para que veas cómo se hace la paginación en JDBC. Y no puede faltar la referencia oficial de JDBC para que te documentes, en lo que se refiere a resultsets que se puedan recorrer.

EDITO: De puro ocio (como si no tuviera trabajo :-| ) me puse a ver posteos pasados, éste tipo de temas ya se han tratado aquí, te expongo unos en:
éste enlace,( casualmente aquí se resuelve algo semejante con Hibernate)
éste enlace,
éste enlace

A ver si de algo te sirve..

Imagen de ajesus

Voy a realizar las pruebas y os cuento

En el proyecto que estoy, uno de los requisitos por contrato es utilizar
hibernate y spring.

Ahora no me preocupa spring, me preocupa recuperar grandes cantidades
de registros que hasta ahora me salta la excepcion de outmemory.

Muchas gracias y en breve os cuento.

Adios

Imagen de ajesus

Por finnnnnnn !

Buenas !

Los enlaces que me remitistes han sido de una utilidad tremenda, pues ademas de solucionar el problema
he entendido algunos conceptos que no tenia claros.

Gracias al primer enlace, con la solucion de AlexSnake he podido dejar perfectamente solucionado el asunto
de la memoria cache, he probado a leer 3.000.0000 de registros del tiron y funcionaaaaa.

Muchas gracias neko069 y a todos los demas, pues desde que empece con Java en todo momento me habeis
ayudado un monton.

Gracias y gracias ...
Hasta Luego

Imagen de neko069

:-)

Qué bien que se solucionó tu problema :-)
Para cerrar con broche de oro, sería bueno que postearas el código ganador, si no puedes publicar el original, pues un ejemplo que esté basado en tu solución, con el fin de que quede para otros desarrolladores que lleguen a tener el mismo problema.
Saludos.

Imagen de ajesus

Mi gozo en un pozo !

He tardado en mostrar el codigo que me pedias, pero es que no habia entrado en el foro.

Y precisamente antes de postearlo, he metido el while dentro del metodo pues en el caso real
lo tengo fuera. Mi sorpresa a sido que al probarlo con 3.000.0000 de registro ha dado de nuevo
el error java.lang.OutOfMemoryError y he comprobado que por error habia realizado las pruebas con
180.000. La verdad es que esta solucion funciona bastante mejor que antes de implementar la
solucion que me propusiesteis.

Adjunto el codigo, que va bastante bien, pero ......., yo espero implentar una solucion que me olvide
de tener que preocuparme de la cantidad de registro que me devuelve una consulta.

Adjunto el codigo y marco la linea donde da el error, espero que me podais aportar alguna idea.

@Override
public ScrollableResults HibernateQueryRegisterLot(Object object) {
_logger.info("HibernateQueryRegisterLot");

ScrollableResults ClaseScroll = null;
sessionFactory = HibernateCreateSessionFactory();
Session session = sessionFactory.getCurrentSession();

try {
HibernateBeginTransaction(session);
Criteria criteria = session.createCriteria(object.getClass());
//criteria.add(Restrictions.between("id", 1, 3000000));

****** error es producido en esta sentencia
ClaseScroll = criteria.setCacheMode(CacheMode.IGNORE).scroll(
ScrollMode.FORWARD_ONLY);
****** error es producido en esta sentencia

File fichero = new File("c:/tmp/hola.txt");
if (fichero.exists())
fichero.deleteOnExit();
BufferedWriter bw = new BufferedWriter(new FileWriter(fichero));

int contador = 0;

while (ClaseScroll.next()) {
object = ((Object) ClaseScroll.get(0));
bw.write(contador);
bw.newLine();

if (contador % 5000 == 0) {
System.out.println("Limpio !");
HibernateFlush(session);
HibernateClear(session);
HibernateSystemGc();
}
System.out.println(contador);
contador++;
}
bw.close();
} catch (Exception e) {
_logger.info("Error : " + e);
// e.printStackTrace();
} finally {
}

return ClaseScroll;
}

Imagen de ajesus

Leer miles de registros Hibernate

Vuelvo a lanzar el mismo asunto , pues pienso que mi respuesta no ha sido leida.

He tardado en mostrar el codigo que me pedias, pero es que no habia entrado en el foro.

Y precisamente antes de postearlo, he metido el while dentro del metodo pues en el caso real
lo tengo fuera. Mi sorpresa a sido que al probarlo con 3.000.0000 de registro ha dado de nuevo
el error java.lang.OutOfMemoryError y he comprobado que por error habia realizado las pruebas con
180.000. La verdad es que esta solucion funciona bastante mejor que antes de implementar la
solucion que me propusiesteis.

Adjunto el codigo, que va bastante bien, pero ......., yo espero implentar una solucion que me olvide
de tener que preocuparme de la cantidad de registro que me devuelve una consulta.

Adjunto el codigo y marco la linea donde da el error, espero que me podais aportar alguna idea.

@Override
public ScrollableResults HibernateQueryRegisterLot(Object object) {
_logger.info("HibernateQueryRegisterLot");

ScrollableResults ClaseScroll = null;
sessionFactory = HibernateCreateSessionFactory();
Session session = sessionFactory.getCurrentSession();

try {
HibernateBeginTransaction(session);
Criteria criteria = session.createCriteria(object.getClass());
//criteria.add(Restrictions.between("id", 1, 3000000));

****** error es producido en esta sentencia
ClaseScroll = criteria.setCacheMode(CacheMode.IGNORE).scroll(
ScrollMode.FORWARD_ONLY);
****** error es producido en esta sentencia

File fichero = new File("c:/tmp/hola.txt");
if (fichero.exists())
fichero.deleteOnExit();
BufferedWriter bw = new BufferedWriter(new FileWriter(fichero));

int contador = 0;

while (ClaseScroll.next()) {
object = ((Object) ClaseScroll.get(0));
bw.write(contador);
bw.newLine();

if (contador % 5000 == 0) {
System.out.println("Limpio !");
HibernateFlush(session);
HibernateClear(session);
HibernateSystemGc();
}
System.out.println(contador);
contador++;
}
bw.close();
} catch (Exception e) {
_logger.info("Error : " + e);
// e.printStackTrace();
} finally {
}

return ClaseScroll;
}

style="display:inline-block;width:728px;height:90px"
data-ad-client="ca-pub-5164839828746352"
data-ad-slot="7563230308">