4.1 Parametrar för frågor

Hibernate låter dig skicka parametrar till frågor. Allt arbete med frågor och databasen förenklas alltså avsevärt.

Det är mycket sällsynt att hitta oföränderliga frågor. Till en början verkar det som att du bara behöver returnera en lista över varor från databasen. Och så visar det sig att du behöver en uppdaterad lista över produkter för en specifik användare vid ett specifikt datum. Sorterat efter det obligatoriska fältet och ännu inte hela listan, utan en specifik sida: till exempel produkter från 21 till 30.

Och det är precis vad parameteriserade frågor löser. Du skriver en fråga i HQL och ersätter sedan värdena som kan ändras med "speciella namn" - parametrar. Och sedan separat när du utför begäran kan du skicka värdena för dessa parametrar.

Låt oss skriva en HQL-fråga som returnerar alla uppgifter för en användare med ett specifikt namn:

from EmployeeTask where employee.name = "Ivan Ivanovich"

Låt oss nu ersätta namnet med en parameter:

from EmployeeTask where employee.name = :username

Och så här kommer vår Java-kod för att hitta uppgifter att se ut:


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

Dessutom, istället för ett parameternamn, kan du bara använda ett nummer:


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

Även om det är bättre, naturligtvis, att använda namnet - det är mycket lättare att läsa och underhålla sådan kod.

4.2 setParameterList() metod.

Det finns också fall då parametervärdet inte är ett, utan representerar en lista med objekt. Vi vill till exempel kontrollera att anställdas yrken finns med i en viss lista.

Hur kunde detta göras:


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

4 typer av listor kan skickas som ett parametervärde:

  • array av objekt: Objekt[]
  • samling: Samling
  • maskinskriven array: T[]
  • maskinskriven samling: Samling<T>

Om du bestämmer dig för att skicka en inskriven samling eller array, måste du skicka datatypen som den tredje parametern. Exempel:


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

När du arbetar med listparametrar kan du även använda ett nummer istället för parameternamnet. Men återigen, namnet är bekvämare.

4.3 Skydd mot SQL-injektion

Ett av de viktigaste syftena med parametrarna är att skydda databasen från SQL-injektioner. Många nybörjare programmerare, istället för att använda parametrar, skulle helt enkelt limma ihop en sträng av flera delar.

Istället för att skriva så här:


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

Skulle skriva så här:


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

Gör aldrig det!Håll aldrig ihop en SQL/HQL-fråga från flera delar. För förr eller senare kommer användarnamnet till dig från klienten. Och den onde hackaren kommer att ge dig en sträng som""Ivan"; DROP TABLE user;"

Och sedan kommer din fråga till databasen att ta formen:


from EmployeeTask where employee.name = "Ivan"; DROP TABLE user;

Och det är fortfarande bra om din data helt enkelt raderas. Du kan också skriva så här:


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

Eller så här:


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