2010-09-23 19 views
4

J'ai deux entités (Dataset et Item), où le premier contient une liste de ce dernier.JPA 2 + Criteria API + obtenir l'élément le plus ancien dans la sous-requête

@Entity 
class Dataset { 
    @Id long id; 
    List<Item> items; 
} 

@Entity 
class Item { 
    @Id long id; 
    @Temporal Date date; 
    String someCriteria; 
} 

Je cherche maintenant tout ensemble de données, qui fait référence à un élément avec someCriteria = dans la liste de l'ensemble de données « x » comme élément le plus ancien (il est la date est antérieure à celle de tous les autres référencés par cette ensemble de données).

Cela devrait fonctionner avec l'API Criteria de JPA-2.0, mais une réponse en tant que requête SQL serait bien aussi.

Voici comment il ressemble en ce moment:

Subquery<Item> _subquery = p_criteria.subquery(Item.class); 
Root<Item> _itemRoot = _subquery.from(Item.class); 
_subquery.select(_itemRoot); 

// correlate 
_subquery.correlate(_datsetRoot); 

// type check 
Predicate _typeP = p_builder.equal(_itemRoot.get(Item_.someCriteria), "x"); 

<additional predicates> 
... 

// reference check 
_subquery.where(_typeP); 

return p_builder.exists(_subquery); 

Je pensais que sur la création d'une sous-requête, l'ordre par date et vérifiez la première. Malheureusement JPA-2.0 ne permet pas de passer des commandes dans les sous-requêtes (ou les jointures) (pour autant que je puisse le voir). Ma deuxième idée était d'obtenir MAX(date), ce qui devrait être pris en charge par la plupart des bases de données. Il en va de même ici, le support pour MAX, ABS, ... n'est disponible que pour les numéros.

EDIT: L'utilisation d'un sous-requête, qui est triée, il ressemblerait à ceci (MSSQL):

SELECT d.id 
FROM Dataset d 
WHERE EXISTS (
SELECT TOP 1 * 
FROM Item i 
WHERE i.dataset_id = d.FALL_ID 
    AND i.someCriteria = 'x' 
ORDER BY i.date 
) 
ORDER BY d.FALL_ID 

(Comment) pourrais-je faire dans JPA-2.0?

+0

Je ne crois pas qu'il n'y a pas de solution pour ce genre de problème. Est-ce que personne n'a d'idée? – Jan

Répondre

6

Dans Java 1.6 il y a les méthodes CriteriaBuilder.least(expression) (au lieu de min()) et CriteriaBuilder.lessThanOrEqualTo(expressionA, expressionB) (au lieu de le()), qui travaillent pour les champs java.util.Date.

Dans Java 1.5, il semble qu'il n'y ait aucun moyen de l'exécuter sans champs supplémentaires dans la base de données.

+1

CriteriaBuilder ne fait pas partie de Java 6 (= Java 1.6), mais de JPA 2.0, qui fait elle-même partie de Java EE 6. Il n'y a pas d'API Criteria (et donc pas de CriteriaBuilder) dans Java 5 (= Java 1.5), JPA 1 ou Java EE 5. – ymajoros