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:
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.
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.
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:
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.
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()); }
?
”
Por ejemplo, para un long
se usará setLong(int position,long val)
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.
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()); }
:nombre
”, “:ape1
” y “:ape2
”.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]
La clase org.hibernate.Query soporta 2 mejoras que simplifican el código Java al usar parámetros.
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:
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).
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:
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()); }
Otra forma de poner los parámetros sería:
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.