Home > Grails, Groovy > Grails ORM część 4 – zapytania

Grails ORM część 4 – zapytania

Marzec 18th, 2009

GORM pozwala nam na wykonywanie zapytań w kilka różnych sposobów. Możemy do nich zaliczyć podstawowe metody operujące na klasach domenowych, dynamic finders (metody typu find*), kryteria (które pozwalają budować zapytania podobnie jak robi to JaQu) albo wykorzystać stary (dobry) HQL.

Metody klas domenowych

Kawałek kodu chyba najlepiej pokaże, jakie metody możemy wywołać:

 
// Wylistuj wszystkie osoby
def persons = Person.list()
// Pobierz osobę o id=3
def person = Person.get(3)
// Pobierz osoby o id 3,4,5
def persons = Person.getAll(3, 4, 5)
// Pobierz 10 osób z offsetem 100, sortując po nazwisku malejąco
def persons = Person.list(max:10, offset:100, sort:"lastname", order:"desc")
 

Dla metody list() możemy dodatkowo określić ilość zwróconych rekordów, od którego rekordu rozpocząć, sortowanie łączenie z kierunkiem, a także w jaki sposób pobrać asocjacje (eager/lazy). Metoda get() po prostu pobiera rekord o zadanym id, a getAll() rekordy o zadanych id. Jeśli któryś z nich nie będzie istniał, lista wyników będzie zawierała null.

Dynamic finders

Dynamic finders to metody tworzone dynamicznie w środowisku uruchomieniowym na podstawie właściwości klasy. Że jak? Że tak:

 
class Person {
    String firstname
    String lastname
    Date dateOfDeath
}
 
def p1 = Person.findByFirstname("Mateusz")
def p2 = Person.findByLastname("Mrozewski")
def p3 = Person.findByFirstnameAndLastnameLike("Mateusz", "M%")
def p4 = Person.findByDateOfBirthIsNull()
 

Wypisane metody to tylko kilka możliwych przykładów. Możemy takie metody wywoływać dla każdej właściwości. Tak jak w przykładzie wyszukania osoby p3 możemy połączyć warunki dla dwóch dowolnych właściwości z operatorem AND lub OR (maksimum dwóch - dla większej ilości powinniśmy wykorzystać kryteria lub HQL). Dwa typy metod to findBy*, który zwraca pierwszy rekord wyniku oraz findAllBy*, który zwraca wszystkie pasujące wyniki. A dozwolone operacje to:

  • InList - czy wartość znajduje się na podanej liście
  • LessThan - czy wartość jest mniejsza niż podana
  • LessThanEquals - czy wartość jest mniejsza lub równa niż podana
  • GreaterThan - czy wartość jest większa niż podana
  • GreaterThanEquals - czy wartość jest większa lub równa niż podana
  • Like - podobne do SQLowego LIKE
  • ILike - jak wyżej, tylko case insensitive (to nie produkt apple'a ;-) )
  • NotEqual - nie równe (nie ma samego equal, bo to równoważne z np. findByName)
  • Between - czy wartość jest pomiędzy zadanymi
  • IsNotNull - czy wartość nie jest null'em
  • IsNull - czy wartość jest null'em

Ten typ zapytań możemy również wykorzystać dla asocjacji. Do tych zapytań możemy też dodać parametry takie jak w metodzie list(). Prawda, że fajne? Osobiście uważam, że przy zastosowaniu już dwóch parametrów przestaje być to czytelne i dużo łatwiej pisze się i analizuje kryteria, ale do prostych zapytań jest to jak najbardziej ciekawe rozwiązanie.

Ale chwileczkę, skąd te wszystkie metody się wzięły? Przecież nic nie dziedziczyliśmy, nic nie implementowaliśmy. Tutaj z pomocą przychodzi nam dynamiczność Groovy oraz to, jak zostało to wykorzystane w Grails. Konkretnie chodzi tu o wykorzystanie metaklas i ich właściwości methodMissing. W książce The Definitive Guide to Grails w dodatku poświęconym Groovy możemy znaleźć nawet prosty przykład implementacji dynamic finder.

Kryteria

Kryteria to sposób na budowanie złożonych zapytań poprzez wykorzystanie składni Groovy. A konkretnie wykorzystana jest tu koncepcja builders.

Nas interesuje jednak jak to wygląda w kodzie. Oto mały przykład z dokumentacji:

def c = Account.createCriteria()
def results = c {
	like("holderFirstName", "Fred%")
	and {
		between("balance", 500, 1000)
		eq("branch", "London")
	}
	maxResults(10)
	order("holderLastName", "desc")
}

W tym przykładzie zostały utworzone kryteria dla klasy domenowej Account. Następnie rozbudowaliśmy je o kolejne warunki - ten prosty przykład chyba dość dobrze pokazuje jakie są możliwości kryteriów.

Co można w takich kryteriach zrobić:

  • wykorzystać wszystkie metody z klasy Hibernate Restrictions
  • wykorzystać operatory logiczne AND, OR i NOT
  • pytać o inne klasy domenowe będące w asocjacji z główną klasą
  • wykorzystać wszystkie metody z klasy Hibernate Projections
  • wykorzystać wszystkie metody z klasy Hibernate ScrollableResults
  • określić ilość pobranych rekordów oraz od którego rekordu zacząć
  • określić czy asocjacje będą pobierane w trybie EAGER czy LAZY

Nie wypisuję wszystkich możliwości, gdyż jest tego mnóstwo, a wszystko jest w Javadoc'ach pod podanymi odnośnikami. Jednak ta krótka przynajmniej pokazuje jak szerokie mamy możliwości. GORM to nie tylko CRUD :)

HQL

W GORM możemy też wykorzystać HQLa (Hibernate Query Language). Jest to język zapytań bardzo podobny do SQLa, ale nie operujemy w nim na tabelkach, tylko na encjach (klasach domenowych). Mamy do dyspozycji trzy metody, które możemy wywołać na naszej klasie domenowej:

  • find - zwraca pierwszy wynik pasujący do zapytania
  • findAll - zwraca wszystkie wyniki pasujące do zapytania
  • executeQuery - wykonuje zapytanie, niekoniecznie zwracając wyniki

Kilka przykładów:

 
// Znajdź pierwszą osobę o imieniu Mateusz
def person = Person.find("from Person as p where p.firstname = ?", ['Mateusz'])
// Znajdź wszystkie osoby o imieniu Mateusz i nazwisku na M
def results = Person.findAll("from Person as p where p.firstname = :firstname and p.lastname like :lastname", [firstname:'Mateusz', lastname:'M%'])
 

Niezbędnikiem jest zapoznanie się z rozdziałem dokumentacji Hibernate poświęconej HQL.

I to tyle jeśli chodzi o wykonywanie zapytań w GORM. Do omówienia zostały jeszcze tematy "zaawansowane", takie jak transakcje, zdarzenia, keszowanie i wpływanie na strukturę bazy danych. Temat na następnego posta.

Grails, Groovy

  1. Marzec 18th, 2009 at 16:25 | #1

    Świetna notka, idealnie skompresowane wszystko, co do wyszukiwania danych w Grails potrzebne :)
    Mi najbardziej podobają się kryteria. Sam miałem dopiero niedawno okazję używać tych z Hibernate i jestem pod ogromnym wrażeniem budowanych za ich pomocą zapytań. Dodatkowo domknięcia, które zaoferował Groovy sprawiają, że jest to rozwiązanie naprawdę estetyczne, a mimo to o ogromnych możliwościach.

  1. No trackbacks yet.