J2EE: Bazy danych c.d. Język zapytań EJB QL
Język EJB QL Pozwala na bardziej zaawansowane wydobywanie danych z bazy niż find() Zapytanie tworzy się przez metodę: manager.createQuery() manager.createNativeQuery() manager.createNamedQuery() Powstający obiekt Query może zostać uruchomiony Najprostszy przykład: lista wszystkich samochodów manager.createQuery("from Samochod s").getResultList();
Język EJB QL Podstawa: klasa Query Pobieranie danych Ustawienia getResultList() getSingleResult() executeUpdate() Ustawienia setFirstResult(int) setMaxResults(int) setParameter(name|position, value|date|calendar) setFlushMode(FlushModeType) setHint(String name, Object value)
Przykłady Cała tabela Jeden rekord Query query = manager.createQuery("from Samochod s"); Collection samochody = (Collection)query.getResultList( ); Jeden rekord Query query = manager.createQuery( "from Samochod s where s.numer='XYZ 123'"); Samochod sam = (Samochod)query.getSingleResult( );
Ustawianie parametrów Parametry wg nazwy Query query = manager.createQuery( "from Samochod s where s.numer=:numer"); query.setParameter("numer","XYZ 123"); Samochod sam = (Samochod)query.getResultList( ); Parametry wg pozycji "from Samochod s where s.numer=?1"); query.setParameter(1,"XYZ 123");
Parametry zagnieżdżone // nazwa to kolumna z klasy Marka!!! public List findByName(String name){ Query query = manager.createQuery( "from Samochod s where marka.nazwa=:nazwa"); query.setParameter("nazwa", name); return query.getResultList(); }
Użycie dat query.setParameter(name, date, temporalType) Trzeci parametr opisuje na jaki typ SQL mapować kolumnę TemporalType.DATE|TIME|TIMESTAMP Query query = manager.createQuery( "from Car c where c.year=:date"); query.setParameter("date", new Date(), TemporalType.DATE); Collection cars = query.getResultList( );
Stronicowanie rezultatów setMaxResults(int limit) setFirstResult(int offset) List getAllCars(int limit, int offset) { Query query = manager.createQuery("from Samochod s"); return query .setMaxResults(limit) .setFirstResult(offset) .getResultList( ); }
Rozszerzanie zapytań Cały obiekt Tylko wybrane kolumny select s from Samochod s Tylko wybrane kolumny select numer, rok from Samochod s Referencje do obiektów powiązanych select numer, marka.nazwa from Samochod s ale nie(!): select nazwa, samochod.numer from Marka m Złączenia select numer, nazwa from Samochod s join s.marka m
Czytanie wielu kolumn List result = manager.createQuery("select number, year from Samochod s").getResultList(); Iterator it = result.iterator(); while(it.hasNext()) { Object[ ] row = (Object[ ])it.next(); String number = (String)row[0]; Date year = (Date)row[1]; }
Tworzenie obiektów na rezultat class CarInfo{ String no; Date pr_year; } ... List result = manager.createQuery("select new CarInfo(number, year) from Samochod s").getResultList(); Iterator it = result.iterator(); while(it.hasNext()) { CarInfo cin = (CarInfo)it.next(); System.out.println(cin.no+" "+cin.pr_year); * UWAGA! Należy dostarczyć odpowiednie konstruktory
Elementy jak w SQL INNER JOIN LEFT JOIN IS NULL BETWEEN, NOT BETWEEN IN, NOT IN LIKE
Elementy specyficzne EJB QL JOIN FETCH IS EMPTY MEMBER OF, NOT MEMBER OF
Funkcje Tekstowe: Matematyczne: ABS, SQRT, MOD LOWER(txt) UPPER(txt) TRIM ([LEADING|TRAILING|BOTH] [sign] txt) CONCAT(txt1, txt2) LENGTH(txt1) LOCATE(txt1, txt2[, start]) SUBSTRING(txt1, start, len) Matematyczne: ABS, SQRT, MOD Datowe: CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP
Inne elementy SQL-like Funkcje agregujące(min, max, sum, avg, count) Fraza DISTINCT Fraza ORDER BY (tylko dla kolumn listowanych) GROUP BY i HAVING Zagnieżdżanie zapytań w WHERE i HAVING ALL, ANY i EXISTS UPDATE i DELETE – dozwolone, ale nie zmieniają automatycznie encji podłączonych (bulk updates)
Inne możliwości Użycie klasycznego SQL Definiowanie "named queries" objekt DataSource objekt NativeQuery Definiowanie "named queries" @NamedQuery("qname","select...") manager.createNamedQuery("qname")
Jak używać zapytań Mniej zapytań – szybsze działanie! Przykład: jak dużo samochodów każdej marki List marki = manager.createQuery("from Marka m") .getResultList(); Iterator it = marki.iterator( ); while (it.hasNext( )) { Marka marka = (Marka)it.next( ); Query query = manager.createQuery( "from Samochod s where marka=:marka"); query.setParameter(„marka", marka); List ilsam = query.getResultList(); System.out.println(marka.getNazwa() + ": " + ilsam.size()); }
Przykład zapytania Popzednio: liczba zapytań = 1+ liczba typów Rozwiązanie jednym zapytaniem: List marki = manager.createQuery( "select m.nazwa, m.typ, count(*) from Marka m"+ "JOIN m.samochody c GROUP BY m.nazwa, " + "m.typ").getResultList(); Iterator it = marki.iterator( ); while (it.hasNext( )) { Object[ ] row = (Object[ ])it.next(); String marka = (String)row[0] + (String)row[1]; Long il = (Long)row[2]; System.out.println(marka+": "+il); }
Przykłady/Ćwiczenia