2013-06-11 8 views
5

Próbuję osiągnąć coś jak poniżej, używając WZP Criteria API:Jak odnieść się do pola specyficznego dla podklasy w CriteriaQuery, gdzie sprawdza się super klasa?

SELECT b FROM Box b JOIN SpecialItem s WHERE s.specialAttr = :specialAttr 

Obiekty są

Box

@Entity 
public class Box implements Serializable { 
    ... 
    @ManyToOne 
    @JoinColumn(name = "item_id") 
    Item item; 
    ... 
} 

Przedmiot

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
public class Item implements Serializable { 
    @Id 
    private String id; 
    ... 
} 

SpecialItem

@Entity 
public class SpecialItem extends Item { 
    private String specialAttr; 
    ... 
} 

Moja próba

EntityManager em = getEntityManager(); 
CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery cq = cb.createQuery(Box.class); 
Root from = cq.from(Box.class); 

// Nothing to specify SpecialItem over Item!  
Join join = from.join("item", JoinType.LEFT); 

// java.lang.IllegalArgumentException: Unable to 
// resolve attribute [specialAttr] against path [null]  
Path p = join.get("specialAttr"); 

Predicate predicate = cb.equal(p, "specialValue"); 
cq.where(predicate); 

Nic więc dziwnego, że zgłasza wyjątek, ponieważ specialAttr nie jest członkiem klasy elementu.

Jak mogę zwrócić wszystkie esy Box, które zawierają SpecialItem, gdzie SpecialItem.specialAttr ma jakąś wartość?

Odpowiedz

10

przypadku używania JPA 2.1 można użyć

"SELECT b FROM Box b WHERE TREAT(b.item as SpecialItem).specialAttr = :specialAttr" 

lub

CriteriaQuery<Box> q = cb.createQuery(Box.class); 
Root<Box> box= q.from(Box.class); 
Join<Box, Item > order = box.join("item"); 
q.where(cb.equal(cb.treat(order, SpecialItem.class).get("specialAttr"), 
    qb.parameter(String.class, "specialAttr"))); 
q.select(Box); 
+0

Dzięki, ale jak mam to zrobić za pomocą API Criteria? – Alex

+3

To wielkie dzięki! Out, jeśli odsetki, jest możliwe rozwiązanie z JPA 2.0? – Alex

+0

Tak, ale w sposób, który może powodować dodatkowe sprzężenia. Konieczne będzie wyraźne określenie złączeń i zbudowanie zapytania w odwrotnym kierunku. Coś jak "wybierz b z pola b, SpecialtyItem si gdzie b.item = si and si.specialAttr =: specialAttr" – Chris

3

Właśnie chcemy przedłużyć odpowiedź Chris dla API kryteria w wygenerowanym meta-modelu.

CriteriaQuery<Box> q = cb.createQuery(Box.class); 
Root<Box> box= q.from(Box.class); 
Join<Box, Item> order = box.join(Box_.item); 
q.where(cb.equal(cb.treat(order, SpecialItem.class).get(SpecialItem_.specialAttr), "searchValue"); 
q.select(Box); 
+0

dziękuję! to nie było tak oczywiste! – dikkini

Powiązane problemy