Procesamiento por lotes Un enfoque ingenuo para insertar 100.000 filas en la base de datos usando Hibernate podría verse así: Esto podría caer sobre una OutOfMemoryException en algún sitio cerca de la fila 50.000. Esto es porque Hibernate tiene en caché todas las instancias de Customer recién instanciadas en el caché de nivel de sesión. En este capítulo te mostraremos cómo evitar este problema. Primero, sin embargo, si estás haciendo procesamiento por lotes (batch processing), es absolutamente crítico que habilites el uso de loteo JDBC, si pretendes lograr un rendimiento razonable. Establece el tamaño de lote JDBC a un número razonable (digamos 10-50): Podrías además querer hacer este tipo de trabajo en un proceso donde la interacción con el caché de segundo nivel esté completamente deshabilitado: Inserciones en lote Al hacer persistentes objetos nuevos, debes limpiar con flush() y llamar a clear() en la sesión regularmente, para controlar el tamaño del caché de primer nivel. Actualizaciones en lote Para recuperar y actualizar datos se aplican las mismas ideas. Adicionalmente, necesitas usar scroll() para sacar ventaja de los cursores del lado del servidor en consultas que devuelvan muchas filas de datos. update/delete en masa Como ya se ha discutido, el mapeo objeto/relacional automático y transparente se refiere al manejo de estado de objetos. Esto implica que el estado del objeto está disponible en memoria, por lo tanto actualizar o borrar (usando UPDATE y DELETE de SQL) datos directamente en la base de datos no afectará el estado en memoria. Sin embargo, Hibernate provee métodos para la ejecución de sentencias del estilo de UPDATE y DELETE de SQL que se realizan a través del Lenguaje de Consulta de Hibernate (Hibernate Query Language o HQL). La pseudo-sintáxis para sentencias UPDATE y DELETE es: ( UPDATE | DELETE ) FROM? ClassName (WHERE WHERE_CONDITIONS)?. Algunos puntos a tener en cuenta: En la cláusula-from, la palabra clave FROM es opcional Puede haber sólo una clase mencionada en la cláusula-from, y no puede tener un alias. No puede especificarse ningún join (bien implícito o explícito) en una consulta masiva de HQL. Pueden usarse subconsultas en la cláusula-where. La cláusula-where es también opcional. Como un ejemplo, para ejecutar un UPDATE HQL, usa el método Query.executeUpdate(): Para ejecutar un DELETE HQL, usa el mismo método Query.executeUpdate() (el método está nombrado para aquellos familiarizados con PreparedStatement.executeUpdate() de JDBC): El valor int devuelto por el método Query.executeUpdate() indica el número de entidades afectadas por la operación. Considera que esto puede o no correlacionarse al número de filas afectadas en la base de datos. Una operación masiva HQL podría resultar en que se ejecuten múltiples sentencias de SQL reales, para joined-subclass, por ejemplo. El número devuelto indica el número de entidades reales afectadas por la sentencia. Volviendo al ejemplo de joined-subclass, un borrado contra una de las subclases puede resultar realmente en borrados contra no sólo la tabla a la que está mapeada esa subclase, sino también la tabla "raíz" y potencialmente tablas de joined-subclass más debajo en la jerarquía de herencia. Ten en cuenta que existen actualmente unas pocas limitaciones con las operaciones HQL masivas, que serán atendidas en lanzamientos futuros; consulta la hoja de ruta de JIRA para más detalles.