2011-08-01 11 views
9

mam struktura klasy tak:JPA Criteria API: nieruchomość zapytań od podklasy

@Entity 
@Inheritance(strategy = InheritanceType.JOINED) 
public abstract class Article { 
    private String aBaseProperty; 
} 

@Entity 
public class Book extends Article { 
    private String title; 
} 

@Entity 
public class CartItem { 
    @ManyToOne(optional = false) 
    public Article article; 
} 

Próbowałem następujących czynności, aby otrzymywać wszystkie CartItems które mają odniesienie do Book z title = 'Foo':

CriteriaBuilder builder = em.getCriteriaBuilder(); 
CriteriaQuery<CartItem> query = builder.createQuery(CartItem.class); 
Root<CartItem> root = query.from(CartItem.class); 
builder.equal(root.get("article").get("title"), "Foo"); 
List<CartItem> result = em().createQuery(query).getResultList(); 

Ale niestety powoduje to błąd (ma to sens dla mnie, ponieważ title jest w Book, a nie w Article ...):

 
java.lang.IllegalArgumentException: Could not resolve attribute named title 
    at org.hibernate.ejb.criteria.path.SingularAttributePath.locateAttributeInternal(SingularAttributePath.java:101) 
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:216) 
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:189) 
... 

Jednak udało mi się osiągnąć to, co chcę używając następującej HQL:

SELECT c, a FROM CartItem c INNER JOIN c.article a WHERE a.title = ? 

Więc dlaczego ostatnia praca i mogę osiągnąć coś podobnego przy użyciu API kryteria?

+0

Nie brakuje Ci 'builder.select (root)'? Ponadto zapytanie o kryteria nie odpowiada kwerendie JPQL. –

+0

Dzięki za komentarz! Hmm, mój 'builder' (z' hibernacji-jpa-2.0-api-1.0.0.Final.jar') nie ma metody 'select()'. Tak, nie odpowiadają, oczywiście, że bardzo mi brakuje ;-) Czy chcesz dodać JOIN do 'Artykułu' na własną rękę? – msonntag

Odpowiedz

1

Nie jestem ekspertem, ale z punktu widzenia OO powiedziałbym, że artykuł nie ma tytułu własności i dlatego nie można go znaleźć w artykule o nazwie CarItem.

Może powinieneś sprawdzić, czy artykuł jest typu Księga.

nie jestem pewien jak to zrobić za pomocą CriteriaBuilder

Criteria c=session.createCriteria(CarItem.class, "caritem"); 
c.add(Restrictions.eq("caritem.class", Book.class)); 
List<Article> list=c.list(); 
1

miałem ten sam problem i znaleźć rozwiązanie dzięki chris (patrz JPA Criteria API where subclass).

Do tego potrzebujesz JPA 2.1, i używasz jednej z metod CriteriaBuilder.treat(). Po prostu zastąp swoją linię builder.equal... przez:

builder.equal(builder.treat(root.get("article"), Book.class).get("title"), "Foo"); 
+0

Pracował jak amulet :) – wuerg