Hibernate, zaawanowane zapytanie Criteria

0

Załóżmy, że mam encje Samochod i Wypadki (przykald bezsensowny, ale na nim mozemy poleciec z objasnieniem problemu).
Mozemy miec wiele wypadkow do 1 samochodu.
Encje sa dobrze przygotowane i sa w bazie.

Jednak potrzebujemy, by manager zwrocil nam liste obiektow, takich ze: mamy samochod i liczbe wypadkow,
no to tworze klase:

WypadkiWrapper { Samochod samochod, int liczbaWypadkow } - liczba wypadkow to ilosc wpisow w tabeli Wypadki z id jako klub obcy danego samochodu

Potrzebuje skorzystac z Criteria (tak chyba najbardziej elegancko) [nawiasem mowiac, jak korzystam z Hibernate, to musze miec funkcjonalnosc createCriteria(), prawda ?; bo aktualnie nie widze dostepu do sesji z poziomu menadzera... ale to juz inna sprawa]

Aby osiagnac zamierzony efekt musze zrealizowac zapytanie:

Select Samochod.nazwa, count(Wypadki.SamochodID) from Samochod.nazwa join Wypadki on Samochod.ID == Wypadki.Samoc_ID groupBy (Samochod) - jest to ok?

jak to moge zrealizowac w HibernateCriteria tak mnie wiecej ? (zawsze robilam proste zapytania typu zwroc cos, majace przewaznie linijke, a tu takie zlozone teraz)

Czy moze lepszym rozwiazaniem bedzie HQL, czy natyrny sql, jesli tak, to dlaczego (ale watpie) ?

0

znalazlam takie cos:
List result = session.createCriteria(SomeTable.class)
.add(Restrictions.ge("someColumn", xxxxx))
.setProjection(Projections.projectionList()
.add(Projections.groupProperty("someColumn"))
.add(Projections.max("someColumn"))
.add(Projections.min("someColumn"))
.add(Projections.count("someColumn"))
).list();

wiec w sumie wyglada to przejrzyscie. Zostaja dwa pytania ?

Dlaczego nie mam w projekcie dostepu do session i do createCriteri() ? (mam dostęp do entity managera z createQuery, ale nie ma createCriteria)

  • musze zapytac kogos z projektu jak dostac sie do tego createCriteria ? (korzystajac z jpa/hibernate zawsze musze miec funkcjonalnosc createCriteria, prawda ?)

Co zrobic z tym, że moje zapytanie bedzie zwracac [Nazwa samochodu, liczba wypadkow]*, musze zwrocic przeciez liste pojedynczych elementow, jak zrobic by zapytanie zwrocilo tego SamochoWrapera ?

0

Gosiu Criteria to jest coś specyficznego dla Hibernate. Jeśli korzystasz z JPA to nie masz do niego dostępu i dostawca JPA nie ma tu znaczenia.

0

no to zapewne jak tego nie widzialam, to korzystam z czystego JPA...

czy tutaj za pomoca tego createQuery z JPA jestem w stanie osiagnac taka funkcjonalnosc jaka daje createCriteria ?
czy moze latwiej przejsc na Hibernate (jak to zrobic ?)

0

czyli cos w tym stylu, poidmieniajac selecta na mojego ?:

Query q = em.createQuery("SELECT e.department, AVG(e.salary), COUNT(e) " +
"FROM Employee e GROUP BY e.department");
List<Object[]> result = q.getResultList();

0

jop, tak wygląda querry w JPQL :)
ale ale masz jeden błąd. Czemu odbierasz resulty jako liste tablic obiektów? Przecież wiesz dobrze, że pobierasz obiekty tupu Employee

edit:// aa dobra już wiem czemu, chcesz pobrać poszczególne kolumny

kurde ale czy to nie zaburza przypadkiem zwięzłości JPA? Jak Ty teraz updejta będziesz chciała zrobić teraz skoro nie masz powiązań obiektów Entity klasy Employee z danymi które (może) będziesz modyfikować.
Proponowałbym pobieranie całych Employee, no chyba, że jest tego tak dużo, że zależy nam na oszczędzeniu i bazy danych i przepustowości.

edit2://
Btw czy możliwe jest wykorzystywanie instrukcji agregujących (avg) z instrukcjami które zwracają wiersze ?? no raczej nie ;

0

ogolnie ten sposob daje na rezerwe, bo jest brzydki ze stringiem w zapytaniu, to zapytanie jest na bank dobre, bo skopiowalem przyklad ze strony.

Nie moge skorzystac z CreateCriteria (korzystam z czystego JPA)

sprobuje uzyc createQuery z JPA:

zapytanie, ktore chce zrealizowac:
Select Samochod, count(Wypadki.SamochodID) from Samochod join Wypadki on Samochod.ID == Wypadki.Samochod_ID groupBy (Samochod)

Encja Wypadki, ma pole samochod_ID, ktore jest kluczem obcym w relacji wiele wypadkow do 1 samochodu (po stronie bazy jest to ok zrealizowane)

Moje zapytanie:

CriteriaQuery<Samochod> q = cb.createQuery(Samochod.class);
Root<Samochod> c = q.from(Samochod.class);
Join<Samochod, Wypadki> p = c.join("Samochod_ID", JoinType.LEFT);
q.select(c, cb.count(c.get("samochod_ID")));
q.groupBy(c);

czy to jest ok, widzicie jakies rzucajace sie w oczy bledy ?

jak zrealizowac jakis warunek, po joinie pasuje uzyc "on", ale nie ma czegos takiego, w createQuery nalezy moze uzyc where, wiecie ?

z gory dzieki za wskazowki

0

no np. ja znalazlam juz wczesniej taki sposob, wydaje sie prostszy:

CriteriaQuery<Country> q = cb.createQuery(Country.class);
Root<Country> c = q.from(Country.class);
Join<Country, Capital> p = c.join("capital", JoinType.LEFT);
q.multiselect(c, p.get("name"));

tylko tu mamy, ze Country ma w encji pole Capital capital, ktore jest kluczem obcym.
Ja potrzebuje jednak odwrotnej sytuacji, chce zwrocic Samochod i liczbe wypadkow, ale to klasa wypadek ma pole Samochod kluczObcy, nie bardzo widze, jak moge to odwrocic

0

Shalom, podales Gosi linka, ale na moje oko średnio da sie to zrobic wedlu tego...

Gosia ma taka sytuacje:

klasa Samochod z adnotacjami Hibernate, oraz klase Wypadki:

@Entity
class Wypadek{
...

@ManyToOne
Samochod samochod;
}

ona potrzebuje zrobic zapytanie:
Select Samochod Count(Wypadki.samochod) from Wypadki join Samochod on Samochod.ID == Wypadki.Samochod GroupBy Samochod;

na moje oko nie da sie tego zrobic (tu relacja jest odwrocona wzgledem tego co jest napsiane w Twoich linkach Shalom)

Ja tego nie widze, masz moze Shalom (lub ktos inny) jakis pomysl, bo tez mnie to ciekawi...

1 użytkowników online, w tym zalogowanych: 0, gości: 1