Wprowadzenie do interfejsu API kryteriów

Istnieją dwa sposoby pisania zapytań do bazy danych w Hibernate:

  • Hibernacja języka zapytań
  • API kryteriów

Pierwszą poznałeś już dawno temu, czas zapoznać się z API Criteria. To bardzo potężne narzędzie, w pewnym momencie było nawet bardziej popularne niż HQL. Teraz nie jest już tak popularny, ale do niektórych zadań na pewno będzie lepszym rozwiązaniem niż HQL.

W każdym razie nie możesz nauczyć się Hibernate bez zapoznania się z API Criteria. Napiszmy mały przykład, a następnie go przeanalizujemy. Na przykład poprosimy wszystkich pracowników (Employee) z bazy danych. Oto, co otrzymamy:

CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Employee> critQuery = builder.createQuery(Employee.class);

Root<Employee> root = critQuery.from(Employee.class);
critQuery.select(root);

Query<Employee> query = session.createQuery(critQuery);
List<Employee> results = query.getResultList();

Wygląda na skomplikowane. Napiszmy to samo zapytanie HQL dla porównania:

String hqlQuery = "from Employee";

Query<Employee> query = session.createQuery(hqlQuery);
List<Employee> results = query.getResultList();

Zwróć uwagę, że ostatnie dwa wiersze obu przykładów są prawie identyczne: tworzymy obiekt Query i używamy go do uzyskania listy. To sugeruje, że pozostałe linie robią coś identycznego.

Spójrz na wiersze 3 i 4 pierwszego przykładu:

Root<Employee> root = critQuery.from(Employee.class);
critQuery.select(root);

Zapiszmy je w jednym wierszu:

critQuery.select(critQuery.from(Employee.class));

Czy ci to nic nie przypomina? A jeśli pokolorujesz to trochę inaczej:

critQuery.select(critQuery.from(Employee.class));

Tak, to taka skomplikowana konstrukcja zapytania SELECT FROM.

Przykłady pracy z interfejsem API kryteriów

Dla lepszego zrozumienia podam tylko kilka przykładów.

Żądanie 1 . Zdobądź wszystkich pracowników z pensją powyżej 10 tys.:

critQuery.select(critQuery.from(Employee.class)).where(builder.gt(root.get("salary"), 10000));

Żądanie 2 . Zdobądź wszystkich pracowników z pensją poniżej 50 tysięcy:

critQuery.select(critQuery.from(Employee.class)).where(builder.lt(root.get("salary"), 50000));

Żądanie 3 . Zdobądź wszystkich pracowników, których stanowisko zawiera słowo „test”:

critQuery.select(critQuery.from(Employee.class)).where(builder.like(root.get("occupation"), "%test%"));

Prośba 4 . Zdobądź wszystkich pracowników z pensją od 10 do 50 tysięcy:

critQuery.select(critQuery.from(Employee.class)).where(builder.between(root.get("salary"), 10000, 50000));

Prośba 5 . Pobierz wszystkich pracowników, których nazwa jest pusta:

critQuery.select(critQuery.from(Employee.class)).where(builder.isNull(root.get("name")));

Żądanie 6 . Uzyskaj wszystkich pracowników, których nazwa nie jest pusta:

critQuery.select(critQuery.from(Employee.class)).where(builder.isNotNull(root.get("name")));

To taki trudny sposób na zbudowanie zapytania:

  • Najpierw dostajesz przedmiotCriteriaBuilder.
  • Następnie użyj go do stworzenia obiektuZapytanie o kryteria.
  • Następnie zaczynasz dodawać do niego części za pomocąZapytanie o kryteriaICriteriaBuilder.

W ten sposób możesz ustawić parametry dla:

  • WYBIERAĆ
  • Z
  • GDZIE

Używając równieżCriteriaBuildermożesz skonstruować różne warunki dla GDZIE.

Zaawansowana praca z Criteria API

Za pomocą Criteria API możesz skonstruować zapytanie o dowolnej złożoności. I to jest świetna wiadomość. Na przykład potrzebujesz złożonej klauzuli WHERE. Oto jak to zrobić:

Predicate greaterThan = builder.gt(root.get("salary"), 1000);
Predicate testers = builder.like(root.get("occupation"), "test%");

critQuery.select(critQuery.from(Employee.class)).where(builder.or(greaterThan, testers));

Jeśli chcesz napisać AND zamiast OR, wystarczy zmienić ostatnią linię:

critQuery.select(critQuery.from(Employee.class)).where(builder.and(greaterThan, testers));

Wszystko jest właściwie bardzo proste. Podam tabelę z kilkoma porównaniami:

SQL metoda Pełny zapis
a<b lt(a, b) budowniczy.lt(a, b)
a > b gt(a, b) budowniczy.gt(a, b)
a lub B lub (a, b) budowniczy.or(a, b)
a ORAZ b i(a,b) budowniczy.i(a,b)
LIKE b jak (a, b) budowniczy.jak(a, b)
a MIĘDZY (c, d) pomiędzy (a, c, d) budowniczy.między(a, c, d)
a JEST NULL isNull(a) builder.isNull(a)
a NIE JEST NULL isNotNull(a) builder.isNotNull(a)

Wszystko jest proste, prawda?

A jak dodać sortowanie do zapytania? Bardzo prosta:

critQuery.select( critQuery.from(Employee.class) );
critQuery.where( builder.and(greaterThan, testers) );
critQuery.orderBy( builder.asc(root.get("salary"), builder.desc(root.get("joinDate") )

Po prostu wywołujesz obiektZapytanie o kryteriaorderBy () i przekazać do niej wymagane parametry.

Oto jak to samo zapytanie wyglądałoby w HQL. Porównywać:

select * from Employee
where (…) and (…)
order by 'salary' asc, 'joinDate' desc

Musisz tylko pamiętać o 3 rzeczach:

  • Operatory klawiszy, takie jak SELECT, FROM, WHERE, są wywoływane na obiekcieZapytanie o kryteria.
  • Operatory pomocnicze, takie jak AND, OR, DESC, są wywoływane na obiekcieCriteriaBuilder.
  • Nazwy pól są pobierane z obiektu przez get()źródło.