Diferencia entre revisiones de «Eficiencia Ejecutando Querys Con Hibernate»

De Dos Ideas.
Saltar a: navegación, buscar
(Página creada con ' Hibernate provee varias formas de ejecutar un mismo Query HQL, devolviendo los resultados de distintas maneras. La interfaz que se utiliza para la ejecución de queries es pr...')
 
Línea 1: Línea 1:
 +
Hibernate provee varias formas de ejecutar un mismo Query HQL, devolviendo los resultados de distintas maneras. La interfaz que se utiliza para la ejecución de queries es precisamente org.hibernate.Query que provee 3 metodos para obtener los resultados de un Query: list(), iterate() y scroll().
  
Hibernate provee varias formas de ejecutar un mismo Query HQL, devolviendo los resultados de distintas maneras. La interfaz
+
Se analizarán los dos primeros en cuanto a eficiencia y conveniencia de uso.
 
 
que se utiliza para la ejecución de queries es precisamente org.hibernate.Query que provee 3 metodos para obtener los
 
 
 
resultados de un Query: list(), iterate() y scroll(). Se analizarán los dos primeros en cuanto a eficiencia en nuestras
 
 
 
aplicaciones.
 
  
 
== Query.list() ==
 
== Query.list() ==
  
El método Query.list() devuelve en una colección todos los resultados del Query. Es decir, en la colección se encuentran  
+
El método Query.list() devuelve en una colección todos los resultados del Query. Es decir, en la colección se encuentran instanciadas todas las entidades que corresponden al resultado de la ejecución del HQL, por lo tanto el ResultSet subyacente de la conexión JDBC se cierra ya que no se necesita más.  
 
 
instanciadas todas las entidades que corresponden al resultado de la ejecución del HQL, por lo tanto el ResultSet subyacente  
 
 
 
de la conexión JDBC se cierra ya que no se necesita más.  
 
  
 
Notar que esta alternativa realiza una única comunicación con la base de datos en donde se traen todos los resultados y requiere que haya memoria suficiente para almacenar todos los objetos resultantes del query. Si la cantidad de resultados es extensa, el delay del acceso a la base será notorio.
 
Notar que esta alternativa realiza una única comunicación con la base de datos en donde se traen todos los resultados y requiere que haya memoria suficiente para almacenar todos los objetos resultantes del query. Si la cantidad de resultados es extensa, el delay del acceso a la base será notorio.
Línea 29: Línea 20:
  
 
El método Query.iterate() devuelve un iterador java.util.Iterator para iterar los resultados del query.
 
El método Query.iterate() devuelve un iterador java.util.Iterator para iterar los resultados del query.
En este caso, las entidades se instancian "a demanda", es decir, con cada llamada al método Iterator.next() que devolverá la  
+
En este caso, las entidades se instancian "a demanda", es decir, con cada llamada al método Iterator.next() que devolverá la entidad de la posición actual del iterador.
 
 
entidad de la posición actual del iterador.
 
 
 
Para resolver esto, Hibernate ejecuta el query obteniendo sólo los ids de las entidades, y en cada llamada al método next()
 
 
 
ejecuta la consulta propia para obtener la entidad completa. Esto se traduce en una mayor cantidad de accesos a la base de
 
 
 
datos, resultando en un mayor tiempo de procesamiento total. La ventaja de este método es que no se requiere que todas las
 
 
 
entidades estén cargadas en memoria simultáneamente, consumiendo memoria innecesariamente.
 
 
 
Para optimizar la obtención de entidades haciendo que no se realice un acceso a la base por cada  llamada al metodo
 
  
Iterator.next(), se puede fijar la cantidad de resultados a traer en cada acceso o "fetch". Esto se configura llamando al
+
Para resolver esto, Hibernate ejecuta el query obteniendo sólo los ids de las entidades, y en cada llamada al método next() ejecuta la consulta propia para obtener la entidad completa. Esto se traduce en una mayor cantidad de accesos a la base de datos, resultando en un mayor tiempo de procesamiento total. La ventaja de este método es que no se requiere que todas las entidades estén cargadas en memoria simultáneamente, consumiendo memoria innecesariamente.
  
método Query.setFetchSize() antes de la ejecución de la consulta.
+
Para optimizar la obtención de entidades haciendo que no se realice un acceso a la base por cada  llamada al metodo Iterator.next(), se puede fijar la cantidad de resultados a traer en cada acceso o "fetch". Esto se configura llamando al método Query.setFetchSize() antes de la ejecución de la consulta.
  
  
Línea 61: Línea 40:
 
</code>
 
</code>
  
Debe tenerse particular cuidado en que no se cierre la sesión de hibernate mientras se utiliza el iterador, de lo contrario  
+
Debe tenerse particular cuidado en que no se cierre la sesión de hibernate mientras se utiliza el iterador, de lo contrario no se podrán obtener los resultados subsiguientes de la base de datos.
 
 
no se podrán obtener los resultados subsiguientes de la base de datos.
 
  
  
 
== Conclusión ==
 
== Conclusión ==
  
Para los casos en que se deban tener acceso simultáneo a todas las entidades resultantes de un Query, el método Query.list()  
+
Para los casos en que se deban tener acceso simultáneo a todas las entidades resultantes de un Query, el método Query.list() cumplirá con los requisitos, teniendo en cuenta que todos los resultados esperados ocuparán espacio en memoria.  
 
 
cumplirá con los requisitos, teniendo en cuenta que todos los resultados esperados ocuparán espacio en memoria.  
 
 
 
Si lo que se necesita es realizar una operación con cada entidad y luego esa entidad no se utilizará más, el método
 
 
 
Query.iterate() se ajusta mejor ya que permite limitar (con Query.setFetchSize() ) la cantidad de resultados que se tienen en
 
 
 
memoria y no consumir recursos innecesariamente, haciendo que la aplicación sea más eficiente y menos propensa a fallos por
 
  
falta de memoria en casos potenciales de muchos resultados en un query.
+
Si lo que se necesita es realizar una operación con cada entidad y luego esa entidad no se utilizará más, el método Query.iterate() se ajusta mejor ya que permite limitar (con Query.setFetchSize() ) la cantidad de resultados que se tienen en  
  
 +
memoria y no consumir recursos innecesariamente, haciendo que la aplicación sea más eficiente y menos propensa a fallos por falta de memoria en casos potenciales de muchos resultados en un query.
  
  

Revisión del 14:46 16 abr 2009

Hibernate provee varias formas de ejecutar un mismo Query HQL, devolviendo los resultados de distintas maneras. La interfaz que se utiliza para la ejecución de queries es precisamente org.hibernate.Query que provee 3 metodos para obtener los resultados de un Query: list(), iterate() y scroll().

Se analizarán los dos primeros en cuanto a eficiencia y conveniencia de uso.

Query.list()

El método Query.list() devuelve en una colección todos los resultados del Query. Es decir, en la colección se encuentran instanciadas todas las entidades que corresponden al resultado de la ejecución del HQL, por lo tanto el ResultSet subyacente de la conexión JDBC se cierra ya que no se necesita más.

Notar que esta alternativa realiza una única comunicación con la base de datos en donde se traen todos los resultados y requiere que haya memoria suficiente para almacenar todos los objetos resultantes del query. Si la cantidad de resultados es extensa, el delay del acceso a la base será notorio.

Ejemplo:

Query q = session.createQuery("from Auto auto where auto.aniocreacion < 1985 "); List autos = q.list();


Query.iterate()

El método Query.iterate() devuelve un iterador java.util.Iterator para iterar los resultados del query. En este caso, las entidades se instancian "a demanda", es decir, con cada llamada al método Iterator.next() que devolverá la entidad de la posición actual del iterador.

Para resolver esto, Hibernate ejecuta el query obteniendo sólo los ids de las entidades, y en cada llamada al método next() ejecuta la consulta propia para obtener la entidad completa. Esto se traduce en una mayor cantidad de accesos a la base de datos, resultando en un mayor tiempo de procesamiento total. La ventaja de este método es que no se requiere que todas las entidades estén cargadas en memoria simultáneamente, consumiendo memoria innecesariamente.

Para optimizar la obtención de entidades haciendo que no se realice un acceso a la base por cada llamada al metodo Iterator.next(), se puede fijar la cantidad de resultados a traer en cada acceso o "fetch". Esto se configura llamando al método Query.setFetchSize() antes de la ejecución de la consulta.


Ejemplo:

Query q = session.createQuery("from Auto auto where auto.aniocreacion < 1985 "); q.setFetchSize(10); // se obtendrán 10 resultados en cada acceso a la base. Iterator iter = q.iterate(); while ( iter.hasNext() ) {

   Auto auto = (Auto) iter.next();  // fetch the object
   ...
   

}

Debe tenerse particular cuidado en que no se cierre la sesión de hibernate mientras se utiliza el iterador, de lo contrario no se podrán obtener los resultados subsiguientes de la base de datos.


Conclusión

Para los casos en que se deban tener acceso simultáneo a todas las entidades resultantes de un Query, el método Query.list() cumplirá con los requisitos, teniendo en cuenta que todos los resultados esperados ocuparán espacio en memoria.

Si lo que se necesita es realizar una operación con cada entidad y luego esa entidad no se utilizará más, el método Query.iterate() se ajusta mejor ya que permite limitar (con Query.setFetchSize() ) la cantidad de resultados que se tienen en

memoria y no consumir recursos innecesariamente, haciendo que la aplicación sea más eficiente y menos propensa a fallos por falta de memoria en casos potenciales de muchos resultados en un query.


Vea También

http://www.hibernate.org/hib_docs/v3/api/org/hibernate/Query.html Hibernate Query Interface http://www.hibernate.org/hib_docs/reference/en/html/objectstate-querying.html Hibernate Queriying http://static.springframework.org/spring/docs/1.1.5/api/org/springframework/orm/hibernate/HibernateTemplate.html Querys con Spring HibernateTemplate http://articles.techrepublic.com.com/5100-10878_11-1046675.html Deciding between iterators and lists for returned values in Java http://java.sun.com/j2se/1.4.2/docs/api/java/sql/ResultSet.html Interface java.sql.ResultSet