4.1 Parametry żądań
Hibernacja umożliwia przekazywanie parametrów do zapytań. Dzięki temu cała praca z zapytaniami i bazą danych jest znacznie uproszczona.
Bardzo rzadko można znaleźć niezmienne zapytania. Na pierwszy rzut oka wydaje się, że wystarczy zwrócić listę towarów z bazy. A potem okazuje się, że potrzebujesz aktualnej listy produktów dla konkretnego użytkownika na konkretny dzień. Posortowane według wymaganego pola, a nie całej listy, ale określonej strony: na przykład produkty od 21 do 30.
I właśnie to rozwiązują sparametryzowane zapytania. Piszesz zapytanie w HQL, a następnie zamieniasz wartości, które można zmienić na „nazwy specjalne” - parametry. A następnie osobno podczas wykonywania żądania możesz przekazać wartości tych parametrów.
Napiszmy zapytanie HQL, które zwróci wszystkie zadania dla użytkownika o określonej nazwie:
from EmployeeTask where employee.name = "Ivan Ivanovich"
Teraz zastąpmy nazwę parametrem:
from EmployeeTask where employee.name = :username
A tak będzie wyglądał nasz kod Javy do znajdowania zadań:
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();
Ponadto zamiast nazwy parametru możesz użyć tylko liczby:
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();
Chociaż oczywiście lepiej jest używać nazwy - znacznie łatwiej jest czytać i utrzymywać taki kod.
4.2 metoda setParameterList().
Zdarzają się również przypadki, gdy wartość parametru nie jest jedynką, ale reprezentuje listę obiektów. Na przykład chcemy sprawdzić, czy zawody pracowników znajdują się na określonej liście.
Jak można to zrobić:
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();
Jako wartość parametru można przekazać 4 typy list:
- tablica obiektów: Obiekt[]
- kolekcja: Kolekcja
- wpisana tablica: T[]
- wpisana kolekcja: Kolekcja<T>
Jeśli zdecydujesz się przekazać wpisaną kolekcję lub tablicę, musisz przekazać typ danych jako trzeci parametr. Przykład:
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();
Podczas pracy z parametrami listy można również użyć liczby zamiast nazwy parametru. Ale znowu nazwa jest wygodniejsza.
4.3 Ochrona przed SQL Injection
Jednym z najważniejszych celów parametrów jest ochrona bazy danych przed iniekcjami SQL. Wielu początkujących programistów, zamiast używać parametrów, po prostu skleiłoby ciąg kilku części.
Zamiast pisać tak:
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();
Napisałby tak:
String hql = "from EmployeeTask where employee.name = " + "Ivan Ivanovich";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
List<EmployeeTask> resultLIst = query.list();
Nigdy tego nie rób!Nigdy nie łącz razem zapytania SQL/HQL z wielu części. Ponieważ prędzej czy później nazwa użytkownika przyjdzie do Ciebie od klienta. A zły haker da ci ciąg podobny""Ivan"; DROP TABLE user;"
A wtedy Twoje zapytanie do bazy przyjmie postać:
from EmployeeTask where employee.name = "Ivan"; DROP TABLE user;
I nadal dobrze jest, jeśli Twoje dane zostaną po prostu usunięte. Możesz też napisać tak:
from EmployeeTask where employee.name = "Ivan";
UPDATE user SET password = '1' WHERE user.role = 'admin'
Lub tak:
from EmployeeTask where employee.name = "Ivan";
UPDATE user SET role = 'admin' WHERE user.id = 123;
GO TO FULL VERSION