Tabla de Contenidos
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"; String ape1="CORTINA"; String ape2="GARCIA"; Query query = session.createQuery("SELECT p FROM Profesor p where nombre='" + nombre + "' AND ape1='" + ape1 + "' AND ape2='" + ape2 + "' "); List<Profesor> profesores = query.list(); for (Profesor profesor : profesores) { System.out.println(profesor.toString()); }
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
Modelo de Tablas
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"; String ape1="CORTINA"; String ape2="GARCIA"; Query query = session.createQuery("SELECT p FROM Profesor p where nombre=? AND ape1=? AND ape2=?"); query.setString(0,nombre); query.setString(1,ape1); query.setString(2,ape2); List<Profesor> profesores = query.list(); for (Profesor profesor : profesores) { System.out.println(profesor.toString()); }
- 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.
Por ejemplo, para un long
se usará setLong(int position,long val)
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"; String ape1="CORTINA"; String ape2="GARCIA"; Query query = session.createQuery("SELECT p FROM Profesor p where nombre=:nombre AND ape1=:ape1 AND ape2=:ape2"); query.setString("nombre",nombre); query.setString("ape1",ape1); query.setString("ape2",ape2); List<Profesor> profesores = query.list(); for (Profesor profesor : profesores) { System.out.println(profesor.toString()); }
- 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.
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"; String ape1="CORTINA"; String ape2="GARCIA"; Query query = session.createQuery("SELECT p FROM Profesor p where nombre=:nombre AND ape1=:ape1 AND ape2=:ape2"); query.setParameter("nombre",nombre); query.setParameter("ape1",ape1); query.setParameter("ape2",ape2); List<Profesor> profesores = query.list(); for (Profesor profesor : profesores) { System.out.println(profesor.toString()); }
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"; String ape1="CORTINA"; String ape2="GARCIA"; Query query = session.createQuery("SELECT p FROM Profesor p where nombre=:nombre AND ape1=:ape1 AND ape2=:ape2") .setParameter("nombre",nombre).setParameter("ape1",ape1).setParameter("ape2",ape2); List<Profesor> profesores = query.list(); for (Profesor profesor : profesores) { System.out.println(profesor.toString()); }
- 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") .setParameter("nombre",nombre) .setParameter("ape1",ape1) .setParameter("ape2",ape2);
En cualquier caso la forma de poner los parámetros es más una cuestión estética que de funcionamiento.