4.1 Parámetros para solicitudes

Hibernate le permite pasar parámetros a las consultas. Así, todo el trabajo con consultas y la base de datos se simplifica enormemente.

Es muy raro encontrar consultas inmutables. Al principio, parece que solo necesita devolver una lista de productos de la base de datos. Y luego resulta que necesita una lista actualizada de productos para un usuario específico en una fecha específica. Ordenado por el campo requerido, y aún no la lista completa, sino una página específica: por ejemplo, productos del 21 al 30.

Y esto es exactamente lo que resuelven las consultas parametrizadas. Escribe una consulta en HQL y luego reemplaza los valores que se pueden cambiar con "nombres especiales": parámetros. Y luego, por separado, al ejecutar la solicitud, puede pasar los valores de estos parámetros.

Escribamos una consulta HQL que devolverá todas las tareas para un usuario con un nombre específico:

from EmployeeTask where employee.name = "Iván Ivánovich"

Ahora reemplacemos el nombre con un parámetro:

from EmployeeTask where employee.name = :username

Y así es como se verá nuestro código Java para encontrar tareas:


String hql = "from EmployeeTask where employee.name = :username";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter("username", "Iván Ivánovich");
List<EmployeeTask> resultLIst = query.list();

Además, en lugar de un nombre de parámetro, puede usar solo un número:


String hql = "from EmployeeTask where employee.name = :1";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter(1, "Iván Ivánovich");
List<EmployeeTask> resultLIst = query.list();

Aunque es mejor, por supuesto, usar el nombre, es mucho más fácil leer y mantener dicho código.

4.2 Método setParameterList().

También hay casos en los que el valor del parámetro no es uno, sino que representa una lista de objetos. Por ejemplo, queremos comprobar que las profesiones de los empleados están contenidas en una determinada lista.

Como se puede hacer esto:


String hql = "from EmployeeTask where occupation IN (:occupation_list)";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameterList("occupation_list", nueva cadena [] {"Programador", "Probador"});
List<EmployeeTask> resultLIst = query.list();

Se pueden pasar 4 tipos de lista como valor de parámetro:

  • matriz de objetos: Objeto[]
  • colección: Colección
  • matriz escrita: T[]
  • colección escrita: Collection<T>

Si decide pasar una colección o matriz con tipo, debe pasar el tipo de datos como tercer parámetro. Ejemplo:


String hql = "from EmployeeTask where occupation IN (:occupation_list)";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameterList("occupation_list", nueva cadena [] {"Programador", "Probador"}, String.class);
List<EmployeeTask> resultLIst = query.list();

Cuando trabaje con parámetros de lista, también puede usar un número en lugar del nombre del parámetro. Pero de nuevo, el nombre es más conveniente.

4.3 Protección contra Inyección SQL

Uno de los propósitos más importantes de los parámetros es proteger la base de datos de las inyecciones de SQL. Muchos programadores novatos, en lugar de usar parámetros, simplemente unirían una cadena de varias partes.

En lugar de escribir así:


String hql = "from EmployeeTask where employee.name = :username";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter("username", "Iván Ivánovich");
List<EmployeeTask> resultLIst = query.list();

Escribiría así:


String hql = "from EmployeeTask where employee.name = " + "Iván Ivánovich";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
List<EmployeeTask> resultLIst = query.list();

¡Nunca hagas eso!Nunca pegue una consulta SQL/HQL de varias partes. Porque tarde o temprano el nombre de usuario te llegará del cliente. Y el malvado hacker te dará una cadena como""Iván"; DROP TABLE user;"

Y luego su consulta a la base de datos tomará la forma:


from EmployeeTask where employee.name = "Iván"; DROP TABLE user;

Y sigue siendo bueno si sus datos simplemente se eliminan. También puedes escribir así:


from EmployeeTask where employee.name = "Iván";
UPDATE user SET password = '1' WHERE user.role = 'admin'

O así:


from EmployeeTask where employee.name = "Iván";
UPDATE user SET role = 'admin' WHERE user.id = 123;