====== 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: \\ 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 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 [[wpes>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: class Profesor Profesor : int id Profesor : String nombre Profesor : String ape1 Profesor : String ape2 ==== Modelo de Tablas ==== El modelo de tablas es el siguiente: class Profesor <> Profesor : INTEGER id Profesor : VARCHAR nombre Profesor : VARCHAR ape1 Profesor : VARCHAR ape2 ===== ===== 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]] * [[#Nombre]] ===== 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 org.hibernate.Query|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 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 org.hibernate.Query#setString(int, java.lang.String)|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 org.hibernate.Query#setString(int, java.lang.String)|setString(int position,String val) se usará el método correspondiente al tipo del parámetro. Por ejemplo, para un ''long'' se usará org.hibernate.Query#setLong(int, long)|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. 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 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 org.hibernate.Query#setString(java.lang.String, java.lang.String)|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 org.hibernate.Query#setParameter(int, java.lang.Object)|setParameter(int position,Object val) y org.hibernate.Query#setParameter(java.lang.String, java.lang.Object)|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 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 org.hibernate.Query#setParameter(java.lang.String, java.lang.Object)|setParameter(String name,Object val). ==== Métodos encadenados ==== Todos los métodos de la clase org.hibernate.Query|Query que hemos visto para asignar valores a los parámetros retornan el propio objeto org.hibernate.Query|Query. ¿Por qué retornar un objeto org.hibernate.Query|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 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 org.hibernate.Query#setParameter(java.lang.String, java.lang.Object)|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: 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.