2010-06-02 14 views
5

Tengo un problema terrible que, afortunadamente, tiene una respuesta muy simple. Me estoy quedando sin memoria cuando realice una básicaSin memoria al cargar entidades Java

Si tengo código como este:

MyEntity myEntity; 
for (Object id: someIdList) { 
    myEntity = find(id); 
    // do something basic with myEntity 
} 

Y el método find() es un método relacionado EntityManager estándar:

public MyEntity find(Object id) { 
    return em.find(mycorp.ejb.entity.MyEntity.class, id); 
} 

Este El código funcionó hace un par de semanas y funciona bien si hay menos elementos en la base de datos. El error resultante estoy enfrentando es:

java.lang.OutOfMemoryError: límite de sobrecarga GC superó

La excepción viene de vínculo superior oráculo llamar a algunos métodos JDBC de Oracle.

El bucle existe porque un EJBQL como "seleccionar el objeto (o) de MyEntity como o" sobrecargará el servidor de aplicaciones cuando haya muchos registros.

+0

La ejecución de em.clear() no es la respuesta que estoy buscando ... pero lo tendré en cuenta. El problema con este problema es que solía funcionar ... ¡con el mismo nivel de entradas de la base de datos! Y esto plantea otra pregunta: si tengo un bucle, puedo descargar/borrar periódicamente ... pero ¿qué sucede cuando la aplicación simplemente se ejecuta durante un período prolongado? ¡El EntityManager debe administrar cuánto está administrando! –

+0

El 'EntityManager' tiene la mayor parte del tiempo un ciclo de vida corto (el patrón común es * entitymanager-por-solicitud *). Sugiero leer [5.1. Gestor de entidad y ámbitos de transacción] (http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html_single/#transactions-basics). Si no sigue este patrón, tendrá que lidiar con el "manejo de la memoria". El 'EntityManager' mantiene las entidades en la memoria para rastrear los cambios, así es como funciona JPA, no se puede esperar razonablemente que el' EntityManager' pueda cargar una base de datos completa o eliminar los cambios y separar las entidades por usted. –

Respuesta

8

This code worked a couple of weeks ago, and works fine if there are fewer items in the database. The resulting error I am facing is: java.lang.OutOfMemoryError: GC overhead limit exceeded

Y no hay nada sorprendente aquí. Las entidades cargadas por em.find() se colocan y mantienen en el contexto de persistencia (en la memoria) para rastrear los cambios, de modo que si carga en exceso muchas de ellas sin precauciones, explotará su memoria y obtendrá OOME.

Si realmente necesita hacer algo con todas sus entidades, que necesita para llamar flush() primera para empujar todos los cambios realizados en la base de datos y continuación clear() para despejar el contexto persistente y liberar la memoria a intervalos regulares:

int i = 0; 
for (Object id: someReallyBigIdList) { 
    myEntity = find(id); 
    // do something basic with myEntity 
    if (i % 20 == 0) { //20, same as the JDBC batch size 
     //flush a batch of DML operations and release memory: 
     em.flush(); 
     em.clear(); 
    } 
    i++; 
} 

Calling clear() causas todas las entidades gestionadas que se desprendan. Los cambios realizados a las entidades que no se han descargado a la base de datos no se conservarán. De ahí la necesidad de flush() los cambios primero.

4

El problema es que si hace el ciclo solo consulta una entidad tras otra, pero todavía se hace referencia en su EntityManager. Debe ya sea

  • claro() la entityManager o
  • eliminar la entidad de ella (olvidado cómo se llama la función para esto).

También es una buena idea configurar el administrador de entidades de ser posible, porque eso impide que JPA retenga una copia de cada uno de sus objetos en la memoria, solo para detectar si tiene posibles cambios en caso de una descarga() a la base de datos.

+0

Me acaba de encontrar un problema en Hibernate, poner la entidad como de solo lectura no significa que detenga el contexto persistente para mantener una copia en contexto persistente, todavía se mantendrá, porque la carga/búsqueda posterior buscará una copia del contexto persistente en su lugar de la base de datos. – GMsoF

Cuestiones relacionadas