2013-03-14 10 views
7

Czy można napisać tę kwerendę jako typedQuery i pozwolić dwóm Long'owi trafić w obiekt z dwoma publicznymi polami długimi w środku.TypedQuery zamiast zwykłej kwerendy w JPA

Query q = em.createQuery(
      "SELECT c.id, COUNT(t.id) " + 
      "FROM PubText t " + 
      "JOIN t.comm c " + 
      "WHERE c.element = ?1 " + 
      "GROUP BY c.id"); 
    q.setParameter(1, e); 
    List<?> rl = q.getResultList(); 
    Iterator<?> it = rl.iterator(); 
    HashMap<Long, Long> res = new HashMap<Long, Long>(); 
    while (it.hasNext()) { 
     Object[] n = (Object[]) it.next(); 
     res.put((Long)n[0], (Long)n[1]); 
    } 
    return res; 

Odpowiedz

12

JPA posiada funkcję tylko do tego - konstruktora wyrażeń:

Query q = entityManager.createQuery("SELECT NEW com.example.DTO(c.id, COUNT(t.id)) FROM ..."); 
List<DTO> dtos = q.getResultList(); 

Twoja klasa DTO może być POJO. Wszystko czego będzie potrzebował to publiczny konstruktor akceptujący 2 Long. Pamiętaj, że musisz podać w pełni kwalifikowaną nazwę swojej klasy od operatora NEW.

+0

hi @kostja Otrzymuję komunikat o błędzie (Nie mogę utworzyć TypedQuery dla zapytania z więcej niż jednym zwrotem). Mój SQL wygląda następująco: SELECT NEW com.company.ui.EntityIDKey (c.companyId, c.name) FROM Company c WHERE c.companyId nie ma wartości null, a c.name nie ma wartości null i length (trim (c.name)))> 0 porządku według c.name asc'. Używam TypedQuery w następujący sposób: 'List firmy = getEntityManager(). CreateQuery (sql, EntityIDKey.class) .getResultList();' –

+1

może to mieć miejsce, jeśli twój EntityIDKey nie jest podmiotem. Dostawca może nie obsługiwać takich zapytań. Czy próbowałeś używać zwykłego zapytania? – kostja

+0

jest prawdą, 'EntityIDKey' nie jest jednostką. Korzystam z dostawcy Hibernate i jakoś zakładam, że to zadziała. Regularne zapytanie budujące kolekcję 'Company' działa dobrze. –

8

Nowy kod wygląda teraz tak. Dzięki za pomoc.

TypedQuery<CommUsed> q = em.createQuery(
     "SELECT new CommUsed(c.id,COUNT(t.id)) " + 
     "FROM PubText t " + 
     "JOIN t.comm c " + 
     "WHERE c.element = ?1 " + 
     "GROUP BY c.id", CommUsed.class); 
    q.setParameter(1, e); 
    HashMap<Long, Long> res = new HashMap<Long, Long>(); 
    for (CommUsed u : q.getResultList()) 
     res.put(u.commID, u.cnt); 
+0

Rozumiem, więc możesz w końcu używać TypedQueries :) dobrze wiedzieć. Niestety wydaje się, że nie ma rozsądnego sposobu na wypełnienie "mapy" bezpośrednio z zapytania, więc część transformacji w ostatnich 3 liniach musi zostać, obawiam się. – kostja

+1

Ach, to dobrze. Nie musimy wciskać wszystkiego w jedną linię, jak w starych C dniach. :-) –

+0

@ HasanTuncay, dlaczego nie skorzystałeś z funkcji ekspresji konstruktora sugerowanej przez @kostja? –

Powiązane problemy