unidades:05_hibernate_query_language:01_query
Diferencias
Muestra las diferencias entre dos versiones de la página.
Revisión previa | |||
— | unidades:05_hibernate_query_language:01_query [2023/04/07 22:15] (actual) – admin | ||
---|---|---|---|
Línea 1: | Línea 1: | ||
+ | ====== Query ====== | ||
+ | Hasta ahora nos hemos dedicado a ver las diversas formas de persistencia que soporta hibernate en función de nuestro modelo de objetos de negocio en Java. Pero una característica fundamental de cualquier ORM es la necesidad de leer dichos objetos de la base de datos. | ||
+ | Hibernate tiene el objeto <javadoc h41> | ||
+ | |||
+ | <code java 1|Query> | ||
+ | Query query = session.createQuery(" | ||
+ | List< | ||
+ | for (Profesor profesor : profesores) { | ||
+ | System.out.println(profesor.toString()); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | |||
+ | Lanzar una consulta con Hibernate es bastante simple. Usando la <javadoc h41> | ||
+ | |||
+ | Por último en las líneas de la 4 a la 6 podemos ver cómo usar la lista de objetos '' | ||
+ | |||
+ | < | ||
+ | En la siguiente lección se explica en detalle se explica en detalle el lenguaje de consultas que usa Hibernate, ya que no se usa SQL sino [[02_hql|Hibernate Query Languaje (HQL)]] | ||
+ | </ | ||
+ | |||
+ | ===== Modelo ===== | ||
+ | En los ejemplos que vamos a realizar van a usarse las siguientes clases Java y tablas, que solo mostraremos en formato UML. No vamos a poner el código fuente ni los ficheros de hibernate de mapeo ya que no todas la características que usan han sido explicadas en lecciones anteriores. | ||
+ | |||
+ | ==== Modelo de Java ==== | ||
+ | El modelo de clases Java es el siguiente: | ||
+ | |||
+ | <uml> | ||
+ | class Profesor | ||
+ | Profesor : int id | ||
+ | Profesor : String nombre | ||
+ | Profesor : String ape1 | ||
+ | Profesor : String ape2 | ||
+ | </ | ||
+ | |||
+ | ==== Modelo de Tablas ==== | ||
+ | El modelo de tablas es el siguiente: | ||
+ | |||
+ | <uml> | ||
+ | class Profesor << | ||
+ | Profesor : INTEGER id | ||
+ | Profesor : VARCHAR nombre | ||
+ | Profesor : VARCHAR ape1 | ||
+ | Profesor : VARCHAR ape2 | ||
+ | </ | ||
+ | |||
+ | ===== Query ===== | ||
+ | Pasemos ahora a ver las funcionalidades de la clase <javadoc h41> | ||
+ | |||
+ | ==== list() ==== | ||
+ | Pasemos ahora a ver con más detalle cómo funciona <javadoc h41> | ||
+ | |||
+ | === Lista de Objetos === | ||
+ | Como ya hemos dicho el método <javadoc h41> | ||
+ | |||
+ | <code java 1|Query> | ||
+ | Query query = session.createQuery(" | ||
+ | List< | ||
+ | for (Profesor profesor : profesores) { | ||
+ | System.out.println(profesor.toString()); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | === Lista de Array de Objetos === | ||
+ | Tan y como veremos en la siguiente lección sobre HQL, también se permite que las consultas retornen datos escalares en vez de clases completas. | ||
+ | <code sql> | ||
+ | SELECT p.id, | ||
+ | </ | ||
+ | En la consulta podemos ver cómo en vez de retornar un objeto '' | ||
+ | |||
+ | En estos casos el método <javadoc h41> | ||
+ | |||
+ | Veamos ahora un ejemplo. | ||
+ | |||
+ | <code java 1|Consulta con datos escalares> | ||
+ | Query query = session.createQuery(" | ||
+ | List< | ||
+ | for (Object[] datos : listDatos) { | ||
+ | System.out.println(datos[0] + " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * En la línea 1 vemos cómo se crea el objeto <javadoc h41> | ||
+ | * En la línea 2 se ve que el método <javadoc h41> | ||
+ | * En la línea 4 se inicia el bucle para recorrer cada una de las filas de datos escalares. | ||
+ | * En la línea 5 finalmente se accede a los 2 datos de cada fila mediante '' | ||
+ | |||
+ | === Lista de Objeto === | ||
+ | Hay otro caso cuando hay una única columna en el '' | ||
+ | |||
+ | Si modificamos la anterior consulta de forma que sólo se retorne el nombre, el código quedará de la siguiente forma: | ||
+ | |||
+ | <code java 1|Consulta con sólo un único dato escalar> | ||
+ | Query query = session.createQuery(" | ||
+ | List< | ||
+ | for (Object datos : listDatos) { | ||
+ | System.out.println(datos); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * En la línea 1 ahora la consulta sólo tiene un único dato escalar. | ||
+ | * En la línea 2 el método <javadoc h41> | ||
+ | * En la línea 4 se inicia el bucle para recorrer cada una de las filas de datos escalares pero ahora el tipo es '' | ||
+ | * En la línea 5 finalmente se accede al dato sin el índice del array ya que ha dejado de serlo. | ||
+ | ==== uniqueResult() ==== | ||
+ | En muchas ocasiones una consulta únicamente retornará cero o un resultado. En ese caso es poco práctico que nos retorne una lista con un único elemento. Para facilitarnos dicha tarea Hibernate dispone del método <javadoc h41> | ||
+ | |||
+ | Este método retornará directamente el único objeto que ha obtenido la consulta. En caso de que no encuentre ninguno se retornará '' | ||
+ | |||
+ | <code java 1|uniqueResult()> | ||
+ | Profesor profesor = (Profesor) session.createQuery(" | ||
+ | System.out.println(" | ||
+ | </ | ||
+ | |||
+ | Vemos cómo, gracias al método <javadoc h41> | ||
+ | |||
+ | <note tip> | ||
+ | Al igual que ocurre con <javadoc h41> | ||
+ | </ | ||
+ | |||
+ | <note important> | ||
+ | Si el método <javadoc h41> | ||
+ | |||
+ | org.hibernate.NonUniqueResultException: | ||
+ | </ | ||
+ | ==== Paginación ==== | ||
+ | La paginación es parte fundamental de cualquier aplicación ya que una consulta puede tener miles de resultados y no queremos mostrarlos todos a la vez. | ||
+ | |||
+ | Para conseguir paginar el resultado de una consulta la clase <javadoc h41> | ||
+ | * <javadoc h41> | ||
+ | * <javadoc h41> | ||
+ | |||
+ | Al realizar la paginación son necesarios al menos 2 valores: | ||
+ | * El tamaño de la página | ||
+ | * El nº de la página a mostrar | ||
+ | |||
+ | Con esos 2 valores hemos creado el siguiente código Java que muestra una única página en función del '' | ||
+ | |||
+ | <code java 1|Mostrar el contenido de una única página> | ||
+ | int tamanyoPagina = 10; | ||
+ | int paginaAMostrar = 7; | ||
+ | |||
+ | Query query = session.createQuery(" | ||
+ | query.setMaxResults(tamanyoPagina); | ||
+ | query.setFirstResult(paginaAMostrar * tamanyoPagina); | ||
+ | List< | ||
+ | |||
+ | for (Profesor profesor : profesores) { | ||
+ | System.out.println(profesor.toString()); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | * Las líneas 1 y 2 establecen los valores necesarios para poder mostrar la página, que son el tamaño de la página y el nº de la página a mostrar. | ||
+ | * En la línea 4 se crea la <javadoc h41> | ||
+ | * En la línea 5 se llama al método <javadoc h41> | ||
+ | * En la línea 6 se llama al método <javadoc h41> | ||
+ | * Por fín, en la línea 7 se obtienen únicamente los resultados de la página solicitada. | ||
+ | * Por último en las líneas 9,10 y 11 se muestran los datos. | ||
+ | |||
+ | El mayor problema que tiene la paginación es determinar el nº de páginas para poder mostrárselo al usuario, para saber el nº de páginas es necesario conocer el nº de objetos que retorna la consulta y la forma mas rápida y sencilla es mediante una consulta que las cuente. | ||
+ | |||
+ | El siguiente código Java calcula el nº de páginas de la consulta. | ||
+ | <code java 1> | ||
+ | long numTotalObjetos = (Long) session.createQuery(" | ||
+ | int numPaginas =(int) Math.ceil((double)numTotalObjetos / (double)tamanyoPagina); | ||
+ | </ | ||
+ | |||
+ | * En la línea 1 realizamos la consulta de '' | ||
+ | * En la línea 2 de divide el nº total de objetos entre el tamaño de la página obteniéndose el nº total de páginas. | ||
+ | |||
+ | <note tip> | ||
+ | Al hacer la división para calcular el nº de páginas es necesario hacer el cast de los 2 valores a '' | ||
+ | </ | ||
+ | ===== Consultas con nombre ===== | ||
+ | En cualquier libro sobre arquitectura del software siempre se indica que las consultas a la base de datos no deberían escribirse directamente en el código sino que deberían estar en un fichero externo para que puedan modificarse fácilmente. | ||
+ | |||
+ | Hibernate provee una funcionalidad para hacer ésto mismo de una forma sencilla. En cualquier fichero de mapeo de Hibernate se puede incluir el tag ''< | ||
+ | |||
+ | En el siguiente ejemplo podemos ver cómo se ha definido una query en el fichero '' | ||
+ | <code xml 1|query con nombre " | ||
+ | <?xml version=" | ||
+ | < | ||
+ | < | ||
+ | <class name=" | ||
+ | <id column=" | ||
+ | < | ||
+ | < | ||
+ | < | ||
+ | </ | ||
+ | | ||
+ | | ||
+ | <query name=" | ||
+ | SELECT p FROM Profesor p | ||
+ | ]]></ | ||
+ | </ | ||
+ | </ | ||
+ | |||
+ | Vemos cómo en las líneas 12, 13, y 14 se ha definido la consulta llamada '' | ||
+ | ==== Tag < | ||
+ | Este tag tiene los siguientes datos: | ||
+ | * '' | ||
+ | * // | ||
+ | |||
+ | <note tip> | ||
+ | Hacer notar que la consulta se ha incluido dentro de la instrucción '' | ||
+ | |||
+ | '' | ||
+ | </ | ||
+ | |||
+ | ==== Código Java === | ||
+ | |||
+ | Para hacer uso de una consulta con nombre usaremos el método <javadoc h41> | ||
+ | |||
+ | <code java 1|Uso de una query con nombre> | ||
+ | Query query = session.getNamedQuery(" | ||
+ | List< | ||
+ | for (Profesor profesor : profesores) { | ||
+ | System.out.println(profesor.toString()); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Como podemos ver el uso de consultas con nombre es muy sencillo al usar Hibernate. |