JPA-QL jest językiem z kontrolą typu i każde wyrażenie ma swój typ. Typ wyrażenia wyznaczany jest z jego struktury, typów schematu abstrakcyjnego (AST) deklaracji zmiennych identyfikujących, typów pól trwałych i relacji oraz typy samych literałów (stałych).
Typ abstrakcyjnego schematu (AST, ang. abstract schema type) encji jest wyznaczony przez klasę encji i metadanych dostarczanych w postaci adnotacji lub zapisów w deskryptorze XML (stąd też istnieje możliwość stworzenia narzędzi mapujących, które nie wymagają uruchomienia aplikacji. Hint! Hint! ;-)).
Nieformalnie, typ abstrakcyjnego schematu encji może być zdefiniowany następująco:
- Dla każdego pola trwałego lub metody odczytującej pole trwałe w klasie encji, istnieje pole (pole-stanu, ang. state-field), którego AST odpowiada typowi pola lub wyniku metody, odpowiednio.
- Dla każdego pola relacji lub metody odczytującej pole relacji w klasie encji, istnieje pole (pole-wiązania, ang. association-field), którego AST odpowiada typowi związanej encji (lub jeśli relacja jest jeden-do-wielu lub wiele-do-wielu, ich kolekcji).
Jeśli ktokolwiek mógłby zastanawiać się po co tak dokładne wyjaśnianie mechanizmu typów w JPA-QL, to spieszę wyjaśnić, że znajomość AST pozwala na budowanie poprawnych zapytań JPA-QL. Wydaje się, że nie ma co wyjaśniać, ale znaczenie zrozumienia AST wzrasta ze wzrostem skomplikowania zapytania (postaram się coś wymyśleć jako przykład ;-)).
Obszar działania (domena) zapytania (ang. query domain) składa się z AST wszystkich encji, które są zdefiniowane w pojedyńczym PU.
Obszar działania zapytania może zostać zawężony przez zasięg (ang. navigability) relacji encji, na której jest oparte. Pole-wiązania w AST encji wyznacza zasięg. Korzystając z pól-wiązania i ich wartości, zapytanie może obejmować encje i używać ich AST w zapytaniu.
Próbując zrozumieć AST można pomyśleć o sieci powiązań między encjami. Mamy sieć (albo jak kto woli graf), w której powiązania wyznaczają drogę (ścieżki). Każdy AST wyznacza ścieżki od encji. Jeśli encja nie jest w relacji z innymi encjami, wtedy AST sprowadza się do typów pól/właściwości encji. Encje w relacji z innymi encjami mają bardziej rozbudowany AST, gdzie powiązanie encji tworzy AST złożone i podążając ścieżkami możemy dotrzeć do nowych AST związanych encji i je wykorzystywać w zapytaniu. Dalsze wyjaśnienia w przykładach za moment i w samej specyfikacji.
4.3.1 Nomenklatura (nazewnictwo)
Encje są określone w zapytaniu poprzez ich nazwy. Nazwa encji jest zdefiniowana przez element name adnotacji @Entity (lub element entity-name w deskryptorze XML). Wartość domyślna dla nazwy encji to niekwalifikowana nazwa klasy encji.
Dla przykładu klasa pl.jaceklaskowski.jpa.entity.Projekt reprezentuje encję, której nazwą jest Projekt (co jest równoznaczne z udekorowaniem klasy adnotacją @Entity(name = "Projekt")).
package pl.jaceklaskowski.jpa.entity;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Projekt implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String nazwa;
public Projekt(String nazwa) {
this.nazwa = nazwa;
}
public String getNazwa() {
return nazwa;
}
public void setNazwa(String nazwa) {
this.nazwa = nazwa;
}
}
podczas, gdy ta sama klasa opatrzona adnotacją @Entity(name = "EncjaProjektu") reprezentowałaby encję o nazwie EncjaProjektu.
Nazwy encji muszą być unikatowe w ramach pojedyńczego PU. Wywnioskować można z tego, że ta sama encja może przyjmować inne nazwy w różnych PU oraz dodatkowo, że encja o nazwie X może wskazywać na różne klasy encji w różnych PU.
Sekcja 4.3.2 Example przedstawia przykład kilku encji (Order, Product, LineItem, ShippingAddress oraz BillingAddress) i sposób wyznaczania AST. Wydaje się być stosownym korzystanie z diagramów UML do zobrazowania zależności między encjami (czyżby pora powrócić do temu ewaluacji narzędzi UML?).
Znajdziemy tutaj ciekawe zapytanie korzystające z słowa kluczowego JOIN do wyszukania wszystkich zamówień (Order), które nie zostały jeszcze zrealizowane.
Pojawia się uwaga odnośnie słów kluczowych i ich notacji. Zazwyczaj słowa kluczowe w zapytaniu, np. SELECT, FROM, AS, JOIN pisane są z wielkich liter, ale nie jest to wymagane. Wielkość liter nie jest istotna i korzystanie z SeLeCt jest równie poprawne jak SELECT, czy select.
Poniższy przykład jest bardzo zbliżony do przykładu ze specyfikacji, tym razem jednak mamy encje Osoba i Projekt, które uczestniczą w relacji jeden-do-wielu (tym razem, ponieważ faktycznie powinno być wiele-do-wielu). Odszukanie wszystkich osób należących do projektu "Apache Geronimo" sprowadza się do następującego zapytania (i tu pojawi się moje pierwsze wykorzystanie JOIN!):
Projekt geronimo = new Projekt("Apache Geronimo");
Osoba jacekLaskowski = new Osoba("Jacek", "Laskowski");
jacekLaskowski.addProjekt(geronimo);
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(geronimo);
em.persist(jacekLaskowski);
tx.commit();
Query query = em.createQuery("SELECT o FROM Osoba o JOIN o.projekty p WHERE p.nazwa = 'Apache Geronimo'");
List<Osoba> osoby = query.getResultList();
assert osoby.size() == 1;
Hej!
OdpowiedzUsuńSekcja 4.3 ostatnio mnie meczy a dokladnie definicji AST i QueryDomain.
Dlaczego? Ano definuje ona QueryDomain jako zbiór wszystkich instancji AST z danego PU. Po ludzku - zapytanie mozemy wydawac dla wszystkich instancji encji z danego PU. Encje w AST maja state-field oraz association-field.
Ale jak wiemy moge miec także cos wiecej jak to obiekty maja rozne property. I tu maly przyklad. Mam encje pracownika, interesuje nas jego wiek wiec zapisujemy date urodzenia. Kwestie aktualnego wieku zalatwiamy przez CallBackMethod (albo w encji albo w jakims listenerze dla encji) i teraz uwaga chcemy wykonac opracja na wszystkich prownikach w wieku 30.
Tu wlasnie lezy przyczna moich mek ;) JPA nie widzi widzi wieku pracownika, jest data urodzenia, imie, nazwisko ale nie wiek bo ten jest tworzny przez CallBackMetode. Czyli tak naprawe QueryDomain ogranicza nas do pol twałych - troche malo skoro mamy operowac na obiektach.
Jesli sie myle bede bardzo wdzieczny jesli ktos za wyprowadzi mnie z bledu i wskaze rozwiazania problemu.
Pzdr