2009-03-24 13 views
6

J'ai deux entités:Comment filtrer la collection en JPA/JPQL?

@Entity 
public class Customer implements java.io.Serializable { 
... 
    @OneToMany(fetch=FetchType.EAGER, mappedBy="customer") 
    private Set<CustomerOrder> customerOrders; 
... 


@Entity 
public class CustomerOrder implements java.io.Serializable { 
....   

    private double cost; 

    @ManyToOne 
    @JoinColumn(name="CUST_ID") 
    public Customer customer; 
... 

Maintenant, dans mon JPQL, je veux revenir les clients avec leur CustomerOrder.cost> 1000. Par exemple, il y a trois clients A, B et C. A a deux ordres avec coût = 1000 et 2000 respectivement. B a trois commandes avec un coût = 2000,3000 et 500 respectivement. C a une commande avec un coût = 500. Maintenant, je veux obtenir les trois clients: A retourne les commandes avec coût = 2000 seulement; B renvoie les ordres avec 2000 et 3000; C renvoie une collection de commandes vide.

Mais ce qui suit renvoie toujours la collection complète:

select c from Customer c, in(c.customerOrders) o where o.cost>1000 

Comment puis-je faire dans JPQL ou Hibernate en particulier?

Répondre

7

La requête affichée est équivalente à

select c from Customer c inner join c.customerOrders o where o.cost > 1000 

qui retourne simplement tous les clients qui ont au moins un ordre avec un coût supérieur à 1000.

Je suggère d'inverser rejoindre et sélectionner les commandes - il est sémantiquement la même chose mais structurellement différent de résultat souhaité que:

select o from CustomerOrder o where o.cost > 1000 

maintenant, Hibernate a une fonction non-JPA appelé filtre qui devrait acco Mplish exactement ce que vous cherchez - voir ici: http://www.hibernate.org/hib_docs/reference/en/html/filters.html

+0

jscoot dit qu'il retourne toutes les lignes , donc votre première requête peut ne pas être équivalente à sa requête puisque C n'a qu'un seul ordre, et son coût est <1000. –

0

Cela ressemble à une mauvaise idée (performance-sage) d'avoir une relation OneToMany là-bas.

Mais pourquoi cela ne fonctionne-t-il pas: select o from CustomerOrder o where o.cost > 1000; puis extrait de la liste des résultats du client?

+0

Pourquoi est-ce une mauvaise idée? –

0

Essayez cette

select c from Customer c join CustomerOrder o with o.cost > 1000 

Il peut renvoyer un client deux fois s'il a deux commandes ayant coût> 1000, que vous pouvez faire groupe par

select c from Customer c join CustomerOrder o with o.cost > 1000 
group by c