viernes, 11 de marzo de 2016

Seteo de parametros de hibernate

Parámetros

En las lecciones anteriores hemos visto cómo, al lanzar una consulta, incluíamos directamente el valor de los parámetros del WHERE. Ëso nos llevaría desde Java a tener un código similar al siguiente:

 1: String nombre="ISIDRO";
 2: String ape1="CORTINA";
 3: String ape2="GARCIA";
 4:
 5: Query query = session.createQuery("SELECT p FROM Profesor p where nombre='" + nombre + "' AND  ape1='" + ape1 + "' AND  ape2='" + ape2 + "' ");
 6: List<Profesor> profesores = query.list();
 7: for (Profesor profesor : profesores) {
 8:     System.out.println(profesor.toString());
 9: }
Como vemos en la línea 2 hemos hecho concatenación de Strings con lo que podrían hacernos Inyección_SQL. La mejor solución a ésto es usar parámetros en las consultas. 

Modelo

En los ejemplos que vamos a realizar van a usarse las siguientes clases Java y tablas, que sólo mostraremos en formato UML. No vamos a poner el código fuente ni los ficheros de hibernate de mapeo ya que aún no han sido explicadas en lecciones anteriores todas la características que usan.

Modelo de Java

El modelo de clases Java es el siguiente:
PlantUML Graph

Modelo de Tablas

El modelo de tablas es el siguiente:
PlantUML Graph
Veamos ahora la forma de usar los parámetros en Hibernate.A diferencia de SQL en la que sólo hay una forma de usar parámetros, en Hibernate se soportan 2 métodos:

Posicional

Esta forma de definir parámetros es muy similar a la que usa SQL.Se basa en definir cada parámetro como un interrogante ”?”. Posteriormente estableceremos a la clase Query el valor de cada uno de los parámetros.
 1: String nombre="ISIDRO";
 2: String ape1="CORTINA";
 3: String ape2="GARCIA";
 4:
 5: Query query = session.createQuery("SELECT p FROM Profesor p where nombre=? AND ape1=? AND ape2=?");
 6: query.setString(0,nombre);
 7: query.setString(1,ape1);
 8: query.setString(2,ape2);
 9:
10: List<Profesor> profesores = query.list();
11: for (Profesor profesor : profesores) {
12:     System.out.println(profesor.toString());
13: }
  • En la línea 5 se define en la consulta HQL cada uno de los 3 parámetros mediante un interrogante ”?
  • En las líneas 6, 7 y 8 se añaden los valores de los parámetros mediante el método setString(int position,String val).
  • El resto de las líneas ya son iguales a cuando no se usaban parámetros.
En caso de que el tipo de parámetro no sea un String, en vez de usar el método setString(int position,String val) se usará el método correspondiente al tipo del parámetro.
Por ejemplo, para un long se usará setLong(int position,long val)
Recuerda que el índice de los parámetros empieza por 0.

Nombre

En este caso los parámetros se definen como nombre precedidos de dos puntos ”:”. Ësto hace que el código sea más legible y menos propenso a error.
 1: String nombre="ISIDRO";
 2: String ape1="CORTINA";
 3: String ape2="GARCIA";
 4:
 5: Query query = session.createQuery("SELECT p FROM Profesor p where nombre=:nombre AND ape1=:ape1 AND ape2=:ape2");
 6: query.setString("nombre",nombre);
 7: query.setString("ape1",ape1);
 8: query.setString("ape2",ape2);
 9:
10: List<Profesor> profesores = query.list();
11: for (Profesor profesor : profesores) {
12:     System.out.println(profesor.toString());
13: }
  • En la línea 5 se puede ver cómo ahora los parámetros son nombres precedidos de dos puntos.En nuestro ejemplo los parámetros son ”:nombre”, ”:ape1” y ”:ape2”.
  • En las líneas 6 , 7 y 8 se asigna valor a los parámetros mediante el método setString(String name,String val).Nótese que ahora se indica el nombre del parámetros en vez de indicar su posición.
  • El resto del código ya es igual al caso anterior.
Recuerda que al establecer los valores de los parámetros en el nombre no hay que poner los dos puntos.
En caso de que erróneamente pongamos los 2 puntos:
query.setString(":nombre",nombre);
Se producirá la excepción:
Exception in thread "main" java.lang.IllegalArgumentException: Parameter :nombre does not exist as a named parameter in [SELECT p FROM Profesor p where nombre=:nombre AND ape1=:ape1 AND ape2=:ape2]

Otras mejoras

La clase org.hibernate.Query soporta 2 mejoras que simplifican el código Java al usar parámetros.

setParameter

Hemos visto cómo el método que usamos para establecer el valor de un parámetro es específico del tipo de dicho parámetro. Ësto hace que tengamos que tenerlo en cuenta al escribir el código con la molestia que ello conlleva.
Para mejorar este hecho existe otra forma de asignar valores a los parámetros que es independiente del tipo.Los métodos son setParameter(int position,Object val) y setParameter(String name,Object val) según si el parámetro es por índice o por nombre.
En ese caso el código quedaría de la siguiente forma:
 1: String nombre="ISIDRO";
 2: String ape1="CORTINA";
 3: String ape2="GARCIA";
 4:
 5: Query query = session.createQuery("SELECT p FROM Profesor p where nombre=:nombre AND ape1=:ape1 AND ape2=:ape2");
 6: query.setParameter("nombre",nombre);
 7: query.setParameter("ape1",ape1);
 8: query.setParameter("ape2",ape2);
 9:
10: List<Profesor> profesores = query.list();
11: for (Profesor profesor : profesores) {
12:     System.out.println(profesor.toString());
13: }
Vemos en las líneas 6, 7 y 8 cómo se ha hecho uso del nuevo método setParameter(String name,Object val).

Métodos encadenados

Todos los métodos de la clase Query que hemos visto para asignar valores a los parámetros retornan el propio objeto Query.
¿Por qué retornar un objeto Query si ya tenemos la referencia a él?
Hacer que los métodos retornen el mismo objeto que los llama es muy útil para poder encadenar métodos sin volver a hacer referencia al objeto.
Veamos un ejemplo para entender la utilidad ésto:
 1: String nombre="ISIDRO";
 2: String ape1="CORTINA";
 3: String ape2="GARCIA";
 4:
 5: Query query = session.createQuery("SELECT p FROM Profesor p where nombre=:nombre AND ape1=:ape1 AND ape2=:ape2")
 6:     .setParameter("nombre",nombre).setParameter("ape1",ape1).setParameter("ape2",ape2);
 7:
 8: List<Profesor> profesores = query.list();
 9: for (Profesor profesor : profesores) {
10:     System.out.println(profesor.toString());
11: }
  • En la línea 5 vemos cómo no se pone el punto y coma final ya que la línea no ha acabado.
  • En la línea 6 (que es continuación de la anterior) se encadenan las 3 llamadas a setParameter(String name, Object val) y al final se pone el punto y coma de final de línea.
Otra forma de poner los parámetros sería:
1: Query query = session.createQuery("SELECT p FROM Profesor p where nombre=:nombre AND ape1=:ape1 AND ape2=:ape2")
2:     .setParameter("nombre",nombre)
3:     .setParameter("ape1",ape1)
4:     .setParameter("ape2",ape2);
En cualquier caso la forma de poner los parámetros es más una cuestión estética que de funcionamiento.

No hay comentarios:

Publicar un comentario